db-derby-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Knut Anders Hatlen <knut.hat...@oracle.com>
Subject Re: Thread-safe shutdown while other threads might try to reopen
Date Tue, 01 Oct 2013 14:46:40 GMT
"Dag H. Wanvik" <dag.wanvik@oracle.com> writes:

> Hi,
>
> I don't believe this situation has changed since 10.8. I agree this
> situation could be improved, so I suggest filing an improvement
> request in JIRA. It would also help if you could supply a self
> contained repro (not strictly necessary, as I believe the description
> is clear enough, but it might just increase the chance of some
> developer looking at it...)

There's already a JIRA issue tracking such an improvement:
https://issues.apache.org/jira/browse/DERBY-4447

Work on the issue seems to have stalled, though.

>
> Thanks,
> Dag
>
> On 01. okt. 2013 11:57, Trejkaz wrote:
>> Hi all.
>>
>> We have an application where there are multiple different contexts and
>> each is isolated from the others (like a webapp). Individual users
>> close and open databases at will. They're opening their own database
>> instance rather than sharing an instance directly, in an attempt to
>> improve the isolation.
>>
>> When all users have disconnected from the database, the admin expects
>> to be able to move the database files aside, so we have to shut the
>> database down when nobody is connected to it.
>>
>> To try and achieve that, we keep our own static reference count. This
>> is done somewhat like this (only the real version uses ConcurrentMap,
>> so there is a lot more boilerplate):
>>
>>      public class Database {
>>          private static final Map<String, Integer> connectionCountMap =
>>              new HashMap<String, Integer>();
>>          private static final Object connectionCountLock = new Object();
>>
>>          private final String path;
>>          private final Connection conn;
>>
>>          public Database(String path) throws SQLException {
>>              this.path = path;
>>              conn = DriverManager.getConnection("jdbc:derby:" + path);
>>          }
>>
>>          public void close() throws SQLException {
>>              conn.close();
>>              decConnectionCount(path);
>>          }
>>
>>          public void incConnectionCount(String path) {
>>              Integer count = connectionCountMap.get(path);
>>              if (count == null) {
>>                  count = 1;
>>              }
>>              connectionCountMap.put(path, count + 1);
>>          }
>>
>>          public void decConnectionCount(String path) {
>>              Integer count = connectionCountMap.get(path);
>>              int countAfterDec = count - 1;
>>              if (countAfterDec > 0) {
>>                  connectionCountMap.put(path, countAfterDec);
>>              } else {
>>                  connectionCountMap.remove(path);
>>                  try {
>>                      DriverManager.getConnection("jdbc:derby:" + path +
>>                           ";shutdown=true");
>>                  } catch (SQLException e) { /* expected */ }
>>              }
>>          }
>>      }
>>
>> What we are finding is that if multiple threads are accessing the same
>> database like this, sometimes one of them will be in the middle of
>> opening a connection while another thread is shutting down the
>> database. I ended up debugging this into Derby and found that the
>> thread opening the database would get a null database reference. Derby
>> would then throw an exception saying the database not found.
>>
>> So the end result is that despite the database files existing on disk,
>> Derby would report that the database was not found, which is wrong in
>> itself...
>>
>> Anyway, setting the incorrect exception message aside, it seems like
>> Derby is thread-hostile in this regard. The docs do say only to
>> shutdown when you know the JVM won't open the database again. The
>> problem with this is that you never know that, so you can never shut
>> it down--so the files never get unlocked.
>>
>> I know I can just slap a synchronized block around these two methods
>> to make it bulletproof, but there are two problems with this:
>>    (1) synchronized is slow and Derby's shutdown is not fast at all...
>>    (2) I don't know what other apps might be open in the same JVM at the same.
>>
>> So I wonder if anyone with experience in this sort of thing has any
>> good tips on how to get around the problem.
>>
>> Also, we're on Derby 10.8, so if anything has been improved in this
>> regard in the later releases, that would be good to know - it might
>> just be enough impetus to switch.
>>
>> TX


Mime
View raw message