----- Original Message ----- From: "Kevin A. Burton" <[EMAIL PROTECTED]> To: "Campbell Boucher-Burnet" <[EMAIL PROTECTED]> Cc: <[EMAIL PROTECTED]> Sent: Friday, March 08, 2002 3:11 PM Subject: Re: [Hsqldb-developers] MORE The database is already in use by another process
> -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > "Campbell Boucher-Burnet" <[EMAIL PROTECTED]> writes: > > > Fred: > > > > I'm not sure I completely agree. As long as the connections are all inside > > the same VM, jdbcConnection can garantee that requests for the same URL all > > share a single instance of the Database, which makes concurrent access safe > > BTW... I also tweaked our connection pool to only use one instance... and it > still failed :( > > > (i.e. openStandalone is syncronized, and Database.execute() is syncronized, > > and instances against each distinct database are cached) and should not result > > in the "Database is un use by..." message: > > > > private synchronized void openStandalone(String user, String password) > > throws SQLException { dDatabase = (Database) > > tDatabase.get(sDatabaseName); > > > > int usage; > > > > if (dDatabase == null) { > > dDatabase = new Database(sDatabaseName); > > > > tDatabase.put(sDatabaseName, dDatabase); > > > > usage = 1; > > } else { > > usage = 1 + ((Integer) iUsageCount.get(sDatabaseName)).intValue(); > > } > > > > iUsageCount.put(sDatabaseName, new Integer(usage)); > > > > cChannel = dDatabase.connect(user, password); > > } > > /* > > NOTE: I just realized a bug in the code above!!! Relative "standalone" > > urls are broken, since we do not cannonicalize the path before puting it in > > the hashtable. Thus, if the current directory is changed inside the JVM and > > a new "standalone" url connection is requested in the relative form, a > > connection to the previously opened instasnce will be returned until the > > usage count against the relative url goes to zero. This needs to be fixed > > or documented in a clear manner. > > */ > /* > Hm... wasn't this only added in JDK 1.4? It might be better to compute absolute > paths on startup. > <snip/> Sorry Kevin...I must be dense...wasn't *what* only added in JDK1.4? Canonicalizing a path? Switching the current directory away from the pwd at the time the VM was invoked? ...? Actually, I've never tried or thought about changing the pwd, I just always assumed setting the system property "user.dir" had some such effect...but looking at the source, the system properties are filled in by a native method in java.lang.System, and putting a system property has only the effect of changing the value in the properties object associated with the key. This seems kinda "hmmm..." to me. It it possible to change the working directory of the JVM process? To be honest, I've never really encountered the need to do this...I just made an assumption, which I shouldn't have. Needs a bit more reading up on, I guess. NOTE 2: Another bug?...if openStandalone does not get a cache hit (i.e. this is the first attempt to connect to the standalone url in question, then it should *not* put the new database instance in the cache (hashtable tDatabase) or up the usage count in iUsageCount until *after* "cChannel = dDatabase.connect(user, password)" succeeds. That is, a try { } block should be put around this and the SQLException should be rethrown in the case of a bad username/password combo, but the tDatabase and iUseage count variables should not be updated (should be located *after* attempting to get the cChannel in the try block). Otherwise, an application could try to connect to a database in standalone mode, fail, and yet theoretically keep that database open forever (at least until the application is closed), blocking all other apps from opening that database. However, there are some other problems associated with this simple code change: The Database class has a finalize method that attempts to shut down the database if it was not already explicitly shut down. This is fine and probably A Good Thing(tm). But, if a connection attempt is the first attempt and fails, it may have taken a while to start up the database (with MEMORY tables or if recovery took place, a potentially large log may have been processed) and if we simply abandon the new dDatabase reference (let it be garbage collected), then it may also take quite some time to finalize (since the database does not checkpoint the log immediatley after a recovery startup), blocking further connection attempts against the related standalone url (or staring up a server instance agasint it) until the finalization has shut down the database completely. Plus, we have wasted a bunch of time for nothing, possibly to experience the same condition in a short amount of time as the user attempts to correct the username/password error and connect again. I can see that the current order of caching is good for cases where the first connection attempt fails and we quickly correct and reconnect (the instance is still hanging around), but it leaves us open to hard-to-understand or unexpected behaviour, for example: the database files are on a network file system and someone tries to connect to the database and can't understand why "The Database is in use by another process," since everybody else claims they are not connected to that set of database files (even though someone actually still is, via an unsuccessful connection attempt, and just don't know it). I suggest there is a good case for persisting user-oriented data using a separate mechanism (a separate cache file containing a single table with user names and (hashed) passwords? who knows...needs some thought to retain ACID properly) so that a Database class instance can construct quickly, process the first connection attempt quickly, and shutdown quickly if it has not moved to the second and much more time-consuming stage (actually mounting the specified database files) because the first connection fails in standalone mode. Obviously, for server modes, a full startup and mount should take place before even the first connection attempt (although I have experimented a bit with lazy init that postpones mounting the database files until first connect, among other lazy initializations). As an aside, perhaps a method should be provided to cause orderly shutdown for the server modes, separate from having to connect as an admin and issue the SQL SHUTDOWN command. It seems JBoss and several other J2EE and/or other application server frame work providers (including some Apache sub-projects?) have already been forced to add this kind of functionality. We should take a look at the needs of the user community and provide this functionality in the form that seems to best suite people's needs. */ > > However, it should *not* be possible to have connections to the same > > standalone database url from separate JVMs/OS processes. Theoretically, one > > should get the "The Database is in use by another process" message every time > > an attempt is made by some process after another process successfully makes > > the first connection. > > OK... what about from multiple threads? What if you have the save JVM but > multiple threads in the above scenario? > > Oh... I see what you are saying... multiple VMs all starting standalone by > themselves on the same on-disk DB.... right. > <snip/> Yes. I don't think we state this clearly enough in the documentation. It seems the posts to Help on this issue are endless. A quick synopis is in order: Server/WebServer mode: unlimited socket-based connections to the instance, but no interface provided to get local (in-process) connections as well Should be provided, though, to acknowlege the fact that there are plenty of folks that would like to run the server modes in-process and also be able to get in-process connections. Example: Server server = new Server(args); Connection internalConection = server.getConnection(user,password); WebServer webServer = new WebServer(args); Connection internalWebServerConection = webServer.getConnection(user,password); Or perhaps this could all be dispensed with via driver properties, as described below... --------------------------------- Standalone/Memory mode: unlimited direct (in-process) connections, but no posiblility of socket-based connections. Should also be provided. Example, via driver properties and via SQL, as in: getConnection("jdbc:hsqldb:path(file path or "." for pure memory operation)[,[create=(true(default)|false(fail if not already created))],[listen=(proto(hsql or http):[addr(default:primaryAdapterInetAddress:][port(default:9001)]]])","usr ","passwd") An interesting possibility this creates is network connections to a volatile (memory mode) instance. Like I stated in my post to Open Discussion, the Database class should be a Server factory. Anyway, I know none of the really helps the problem at hand, but once again: would you let me know in more detail the particulars surrounding getting the "in use" message? It would be nice to set up the same environment, reproduce the case, trace it through, get a full understanding of what is going on and going wrong, and then nail it. Cheers, Campbell > - -- > Kevin A. Burton ( [EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED] ) > Location - San Francisco, CA, Cell - 415.595.9965 > Jabber - [EMAIL PROTECTED], Web - http://relativity.yi.org/ > > The dawn is rising on a new day! > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.0.6 (GNU/Linux) > Comment: Get my public key at: http://relativity.yi.org/pgpkey.txt > > iD8DBQE8iSkdAwM6xb2dfE0RAhZpAKCnKN58ZdL++lJM53SC/ox6OuvLAwCg0Gkk > XCm8PzG40INvCqvtxmZ1lmE= > =0ps/ > -----END PGP SIGNATURE----- > > _______________________________________________ > hsqldb-developers mailing list > [EMAIL PROTECTED] > https://lists.sourceforge.net/lists/listinfo/hsqldb-developers > _______________________________________________ hsqldb-developers mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/hsqldb-developers