This week's book giveaway is in the Agile and Other Processes forum.We're giving away four copies of The Little Book of Impediments (e-book only) and have Tom Perry on-line!See this thread for details.

How to test multi-client?

Darryl Cheung

Greenhorn

Posts: 9

posted 14 years ago

Hi, I have an issue about simulating multi-client testing. I'm using an RMI implementation and I thought that if I invoke my client several times, it would simulate multi-clients and I can see if my locking mechanism is working. I didn't find this the case when I call java.rmi.server.RemoteServer.getClientHost(), every client is the same because they are all running on the same machine. Therefore, one client can unlock another client's record. I don't think this is truly testing the multi-client capabilities of the program. So, I see a lot of people write a test program that spawns threads that act as the client. Is that truly testing the program?? The way I understand RMI is that you create the remote object on the server, bind it to a name, have your client look up that name and call remote methods. The RMI may or may not create new threads to execute the remote methods in. But there is only one server object. Is this correct? Help please! Thanks! Darryl

Mag Hoehme

Ranch Hand

Posts: 194

posted 14 years ago

Hi Darryl, I'm afraid that spawning threads is one of the most important ways to test a multi-client system, and you should not miss the chance to test your app in this way extensively (especially the locking mechanism). There's a number of ways to test a multi-client app, and an app should be tested in various ways. Hope this helps.

Mag

Darryl Cheung

Greenhorn

Posts: 9

posted 14 years ago

Hi Mag, Thanks for the reply. There is no doubt that testing multiple threads is crucial. My concern was that if I use the client host name as the way to uniquely identify clients when locking, I won't be able to test this on my own machine with multiple threads, because all clients have the same name. Therefore, I see it possible to have one thread lock a record and another thread unlock that record. So, this doesn't prove my locking mechanism is working. It seems nobody has addressed this issue so either everyone is taking it on faith that multiple clients on one machine is sufficient to test, or I'm there's something wrong with my reasoning or implementation (maybe I shouldn't use the clientHostName in my locks...) Darryl

Hi Mag, That's a good suggestion. The problem is I don't know how to approach that. The clients don't communicate amoungst themselves so they cannot give themselves a unique name and be sure that every other client has a different name. So the server should do that. But how does the RMI server know when a client has "connected" to it? In a sockets implementation it's explicit when you connect, but in RMI, it's all handled for you so I don't know when and how I should assign the unique name. For example, what method should I be calling? Darryl

Pete Lyons

Ranch Hand

Posts: 109

posted 14 years ago

Darryl, There are extensive discussions in this forum regarding the importance of issuing each client a unique Connection object. This solves your unique ID problem for locking and testing, and let's you use the Unreferenced interface to deal with clients disconnecting while holding lock(s). Look back at the threads with 20+ posts for words like unique, connection, factory, ID, etc. Additionally, there are posts about testing using multiple threads as well as testing by manually using 2 instances of the client application. Pete, SCJD

Darryl Cheung

Greenhorn

Posts: 9

posted 14 years ago

Pete, Thanks for the hint. I think I found what I was looking for and it helped solve my problem. In my old implementation, I bound my DataRemoteImpl object to the RMI. This object has access to all the public methods of Data but gets instantiated only once on the bootstrap server. What I have done now is created a connection manager that also extends UnicastRemoteObject like DataRemoteImpl. However, this is the object that gets bound to the RMI. On the client side, my controller looks up the ConnectionManager through the ConnectionFactory. My connection manager has only one method, to instantiate a DataRemoteImpl object. Now, I have one DataRemoteImpl object per client which can uniquely identify itself to the lock manager when locking. Please comment if that looks correct! Thanks very much! Darryl [ November 17, 2002: Message edited by: Darryl Cheung ]

Peter den Haan

author
Ranch Hand

Posts: 3252

posted 14 years ago

Regarding the testing issue, another approach would be to stick some sleep()s at critical sections in the server. They give you the time to run through some scenarios by hand. - Peter [ November 18, 2002: Message edited by: Peter den Haan ]

jay denzel

Ranch Hand

Posts: 57

posted 14 years ago

Hi, your approach looks fine to me. I did exactly the same thing. Greets, jay

Pete Lyons

Ranch Hand

Posts: 109

posted 14 years ago

Originally posted by Darryl Cheung:

Please comment if that looks correct!

Yes, that's the ticket.

Darryl Cheung

Greenhorn

Posts: 9

posted 14 years ago

Great! Thanks for the help, once again.

HS Thomas

Ranch Hand

Posts: 3404

posted 14 years ago

Daryl, In your amended version , does your DataRemoteImpl still have to extend UnicastRemoteObject ?

Now, I have one DataRemoteImpl object per client which can uniquely identify itself to the lock manager when locking.

Does the connection manager create a new DataRemoteImpl object each time the same client calls it ? If so, how can you ever detect the same object reference to unlock the record locked by the same client ? I am obviously missing something. Please explain. Thanks

Darryl Cheung

Greenhorn

Posts: 9

posted 14 years ago

Originally posted by HS Thomas: Daryl, In your amended version , does your DataRemoteImpl still have to extend UnicastRemoteObject ?

Yes, because my client will be calling the methods of DataRemoteImpl across the network.

Does the connection manager create a new DataRemoteImpl object each time the same client calls it ? If so, how can you ever detect the same object reference to unlock the record locked by the same client ?

Yes, that's correct. In my implementation, whenever a RemoteDataImpl object is created by my Connection Manager, I create a LocK Manager object as well. The Lock Manager has a static counter of clientID's (starting at 0) and just increments it for every Lock Manager instantiated. Then, whenever a client locks a record, the LockManager will stick in the clientID it has for that client into the array of locked records. Now I can tell who locked what. I am not using object references here but the idea is exactly the same. Would it be better to use object references? Maybe, but I think my design is simpler and just as effective. Darryl

HS Thomas

Ranch Hand

Posts: 3404

posted 14 years ago

That's Cool! I prefer the clientId to object reference checks. But, say host 10.20.30 is assigned clientID 1 and locks record no 5, and then subsequently host 10.20.30 calls unlock on record no 5....you have no way of knowing that host 10.20.30 and clientID 1 are the same . Am I right ? In fact , you will have a new clientID generated?

HS Thomas

Ranch Hand

Posts: 3404

posted 14 years ago

Sorry for jumping the gun. Each instance of LockManager would know which clientID number it incremented. In your design , each DataRemoteImpl+LockManager instance represents a client on the server. What are the benefits of this approach? Are there alternatives , like forgetting about the clients , and just synchronising on objects on the server that you have to deal with anyway, like records(or record keys). Would like to know of a resource/link that weighs alternatives to fit real world scenarios. for e.g. Many clients - small catalogue database vs Fewer clients - large knowledge database .

Darryl Cheung

Greenhorn

Posts: 9

posted 14 years ago

Thomas, Well that was my problem since the beginning of this thread. I can have two clients running on the same machine, their host ID's will be the same. But each time the client connects to my server, it will get a different lock manager object. The first client instantiates a lock manager and the static client counter goes to 1. The second client instantiates a lock manager and the static client counter goes to 2. And so on. The benefit of this approach, besides its simplicitiy is that it covers the requirement "only clients who lock those records are allowed to unlock it" which tells me that we should keep track of client ID's. I know some people don't bother tracking them and still do well. If you justify this in your design decision, probably by saying that you guarantee no client ever calls unlock without locking first, then you can probably bypass the requirement. I can think of no other alternatives that satisfy the requirements. I know that your clients need to be named in order to track them. I know that having a centralized naming system is simpler than a distributed naming system. Anyway, those are my thoughts. This whole assignment is about making design decisions really. As long as they are sensible and properly justified, you can pretty much do whatever you want. Darryl

HS Thomas

Ranch Hand

Posts: 3404

posted 14 years ago

Daryl, Thanks for explaining so well. I think I am looking for a design that has as few as possible server-side Objects and Threads. Yours could well be it. An alternative may/may not be found in Bruce Tate's Bitter Java ,specifically page 138: Chapter 5.5 Antipattern: Synchronized Read/Write Bottlenecks page 136 Collisions between readers can hurt performance page 137 Read/write locks allow correct shared access page 138 other alternatives may be in the good books mentioned in this forum.

dennis hu

Ranch Hand

Posts: 40

posted 14 years ago

Hi guys: I also have this problem about test. I test my application in a same machine,so I spawn many threads to test my application. On my client side I spwan 20 threads to book 20 different flights use different reference of of remote server and in each thread I spawn 20 threads again,means every fligh need to be booked 20 times,so there are 400 threas on my client side.But exception occured,there are follows: java.rmi.ConnectionException Connection refused to host 218.242.2.51,nested exception: java.rmi.ConnectionException Connection refused:connect java.rmi.ConnectionException:Exception Creating Connection to host 218.242.2.51,nested exception:java.net.SocketException:Connect(Code:10055) I think maybe the number of threads is too many,so I only use one reference of remote server and spawn 50 threads to book dofferemt flights,but the same exception is still ocurred,and if only spawn 10 threads,it works well,I am so confused. Anybody can help me,Thanks very much!

Darryl Cheung

Greenhorn

Posts: 9

posted 14 years ago

Hi Dennis, I think I saw a thread where someone had the same problem. He spawned many many threads and it basically crashed. I think Mark Spritzler (or one of the gurus here) responded. 400 is way too many and if you can get things working with 10 threads that's probably good enough. Darryl

Darryl Cheung

Greenhorn

Posts: 9

posted 14 years ago

That reminds me, I get a similar exception if I try create the registry with a port other than 1099. Any ideas? A long time ago when I was playing with RMI, I created a security file. I found out it's not needed for this project so I don't invoke it as part of the parameters but the file is still there. Should I get rid of it?