Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
But are you still able to fulfil the requirement that an attempt to write-lock a record twice should return without effect? Probably not.Originally posted by Gennady Shapiro:
I just looked up this design pattern and I like the fact that an incoming request doesn't have identify itself by name or another unique id. This makes it easy to manage lock requests from anonymous users.
The lock manager is commonly implemented using a Map which maps the record number to something identifying the client. You could use a Map mapping the record number to a lock descriptor object, if you wanted. That doesn't sound too bad.This design pattern seems to be concerned with keeping count of read/write-threads for AN OBJECT. [...] Or is that OK to to issue a Lock Manager for every record?
Agreed about "all-or-nothing". The implementation can be far simpler than that however. If you impose the restriction that a client single-threads its database access (not an outlandish requirement; JDBC does it too), then all you have to do is count how many locks are outstanding for that client, wait() until the total number of locks is equal that, then impose the database lock because you know all outstanding locks are yours.Then there is a requirement to be able to lock the entire table. This presents another problem. Locking the whole table is "all-or-nothing" operation. That is, we either lock all the records or fail all together. Now, when such request comes you start locking records one at a time , then you realize that some record is already locked and you have to "rollback".
Synchronization and the wait()... notify() mechanism will do fine to handle "locking the lock". You do need a second-level lock in the sense of a separate database lock, as it is quite a different concept from simply locking all records. For instance, when all records are locked another client should still be able to add a new record. When the database is locked it shouldn't.At this point we need a "second-level" lock, a lock on lock if you will, i dont think simple synchronization will help here.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Mmmm, a layered lock manager where the record lock manager is built on top of the table lock manager? But there is a high degree of coupling between the record locks and the table lock - I'd like to see how you factor these two aspects out. If you can't, you'll end up with two lock manager classes that are so tightly coupled that keeping them separate doesn't make a lot of sense.Originally posted by Gennady Shapiro:
Or is it better to have client wait() for noMoreRecordLocks and your recordLock wait() for noMoreTableLocks. The second approach seems more polymorphic.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
I did account for it, but mainly because it was neat and easy to do, not because I thought it was a requirement. In my design, I handed out a separate database connection to each client, so I could use the java.rmi.server.Unreferenced interface to implement cleanup in three lines of code (along with the fact that it was the simplest design that would handle client identification without changing the signature of the lock methods, this was what convinced me the design was far superior to anything else I had managed to come up with: if the JFC is working with you rather than against you, you must be doing something right).Originally posted by Terry McKee:
Hey Peter, in your design did you account for a lost client connection when a lock was still set? I was thinking of having a timeout value for a lock. Any comments?
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Originally posted by Terry McKee:
As to your first question,
<code>What if the client forgets to use locks</code>
That will never happen if you build the client correctly. It is a programming issue of the client rather than a user issue. (By the way, I am going to implement the lock / unlock methods on the client, but they are just going to call the server methods.)
Originally posted by Terry McKee:
Your second question about breaking a connection. I think this is important, though as Peter mentioned, it isn't part of the requirements. I am planning on having a timestamp value associated with a lock. At startup time of the LockManager the timeout value can be specified OR the default timeout value of 20 seconds can be used. A separate thread will see if the time elapsed is greater than the timeout value. If it is then release the lock.
Now I haven't implemented this scheme yet so I am still working through some things. One of the major issues is that the client may truly continue to need the lock for a long period of time, though unlikely. In this case, it would be nice to keep a reference to the client so that I could throw an exception so they know what happened. Nevertheless, this doesn't have to be 'production' level code so I probably will just release the lock. Either way I will make note of it in my design decisions.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
No, only the ConnectionFactory would be bound to the registry. While the Connection objects it creates are Remote, they are not registered. To the contrary, the "trick" is that each client gets its own Connection that is inaccessible to other clients. See Applying the Factory pattern to RMI. The Connection is also the natural place to implement the remote version of Data you're being asked to do, so it is not just a dummy object - to the contrary.Originally posted by Terry McKee:
What I am getting confused about is this I only have the DataServer registering with the registry. If I follow you correctly then each Connection itself would be bound to the registry. I am just not sure about this.
Are there any situations where Unreferenced won't work, but RMI will? Only if the answer is "yes" this makes sense. But even so this is going to be an intranet type application, where you typically have good control over the environment.As I investigate more about the Unreferenced Interface a few things caught my eye. Depending on the type of network in place the actual implementation of determining whether a client is still connected may not work if bridges, routers, firewalls, etc. are in place. Therefore, I don't think I am going to use it.
The question of whether to use a session ID or a Connection object for identification is mostly orthogonal to the question of whether to use a timeout or Unreferenced for cleanup...I think I am just going to establish a session id for each client.
Say a server - any server - registers a FoobarFactory. Using this factory, one or more clients can create a Foobar object that lives on the server; whether each client gets its own Foobar or whether it is shared is immaterial. You will probably want to clean up the Foobar, and the resources held by it, when all clients using it have died or no longer hold on to it. You can achieve this by simply implementing the Unreferenced interface; the RMI server will call this interface as soon as it thinks all references to the Foobar object have been lost.Though I probably won't use it - I really would like to understand the Unreferenced interface better. Maybe someone could give me example that doesn't have to do directly with the assignment at hand.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
I assume this is an academic question - the database as it stands would groan under 200 users let alone 2 million. But the answer is that it should be pretty scalable. The only state the object has is the link (possibly implicit when realised as an inner class) to a parent class that contains the lock manager and Data, plus what UnicastRemoteObject and RMI add to this. I cannot quantify it but I would be surprised if you wouldn't run into lots of other problems well before you ran into a remote object count limit.Originally posted by Patrick Wang:
If Connection is unique for each client, assume there is no
connection pooling mechanism, do you think it is scalable?
Assume 2 million user concurrently connect to the server at one
time?
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
I was born with webbed fish toes. This tiny ad is my only friend:
We need your help - Coderanch server fundraiser
https://coderanch.com/wiki/782867/Coderanch-server-fundraiser
|