1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.engine; |
7 | |
8 | import java.lang.ref.WeakReference; |
9 | |
10 | import org.h2.message.Trace; |
11 | |
12 | /** |
13 | * This class is responsible to close a database if the application did not |
14 | * close a connection. A database closer object only exists if there is no user |
15 | * connected to the database. |
16 | */ |
17 | class DatabaseCloser extends Thread { |
18 | |
19 | private final boolean shutdownHook; |
20 | private final Trace trace; |
21 | private volatile WeakReference<Database> databaseRef; |
22 | private int delayInMillis; |
23 | |
24 | DatabaseCloser(Database db, int delayInMillis, boolean shutdownHook) { |
25 | this.databaseRef = new WeakReference<Database>(db); |
26 | this.delayInMillis = delayInMillis; |
27 | this.shutdownHook = shutdownHook; |
28 | trace = db.getTrace(Trace.DATABASE); |
29 | } |
30 | |
31 | /** |
32 | * Stop and disable the database closer. This method is called after the |
33 | * database has been closed, or after a session has been created. |
34 | */ |
35 | void reset() { |
36 | synchronized (this) { |
37 | databaseRef = null; |
38 | } |
39 | } |
40 | |
41 | @Override |
42 | public void run() { |
43 | while (delayInMillis > 0) { |
44 | try { |
45 | int step = 100; |
46 | Thread.sleep(step); |
47 | delayInMillis -= step; |
48 | } catch (Exception e) { |
49 | // ignore InterruptedException |
50 | } |
51 | if (databaseRef == null) { |
52 | return; |
53 | } |
54 | } |
55 | Database database = null; |
56 | synchronized (this) { |
57 | if (databaseRef != null) { |
58 | database = databaseRef.get(); |
59 | } |
60 | } |
61 | if (database != null) { |
62 | try { |
63 | database.close(shutdownHook); |
64 | } catch (RuntimeException e) { |
65 | // this can happen when stopping a web application, |
66 | // if loading classes is no longer allowed |
67 | // it would throw an IllegalStateException |
68 | try { |
69 | trace.error(e, "could not close the database"); |
70 | // if this was successful, we ignore the exception |
71 | // otherwise not |
72 | } catch (RuntimeException e2) { |
73 | throw e; |
74 | } |
75 | } |
76 | } |
77 | } |
78 | |
79 | } |