File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\store\WriterThread.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.store;
8
9 import java.lang.ref.WeakReference;
10 import java.security.AccessControlException;
11 import org.h2.Driver;
12 import org.h2.engine.Constants;
13 import org.h2.engine.Database;
14 import org.h2.message.Trace;
15 import org.h2.message.TraceSystem;
16
17 /**
18 * The writer thread is responsible to flush the transaction transaction log
19 * from time to time.
20 */
21 public class WriterThread implements Runnable {
22
23 /**
24 * The reference to the database.
25 *
26 * Thread objects are not garbage collected
27 * until they returned from the run() method
28 * (even if they where never started)
29 * so if the connection was not closed,
30 * the database object cannot get reclaimed
31 * by the garbage collector if we use a hard reference.
32 */
33 private volatile WeakReference<Database> databaseRef;
34
35 private int writeDelay;
36 private Thread thread;
37 private volatile boolean stop;
38
39 private WriterThread(Database database, int writeDelay) {
40 this.databaseRef = new WeakReference<Database>(database);
41 this.writeDelay = writeDelay;
42 }
43
44 /**
45 * Change the write delay
46 *
47 * @param writeDelay the new write delay
48 */
49 public void setWriteDelay(int writeDelay) {
50 this.writeDelay = writeDelay;
51 }
52
53 /**
54 * Create and start a new writer thread for the given database. If the
55 * thread can't be created, this method returns null.
56 *
57 * @param database the database
58 * @param writeDelay the delay
59 * @return the writer thread object or null
60 */
61 public static WriterThread create(Database database, int writeDelay) {
62 try {
63 WriterThread writer = new WriterThread(database, writeDelay);
64 writer.thread = new Thread(writer, "H2 Log Writer " + database.getShortName());
65 Driver.setThreadContextClassLoader(writer.thread);
66 writer.thread.setDaemon(true);
67 return writer;
68 } catch (AccessControlException e) {
69 // // Google App Engine does not allow threads
70 return null;
71 }
72 }
73
74 public void run() {
75 while (!stop) {
76 Database database = databaseRef.get();
77 if (database == null) {
78 break;
79 }
80 int wait = writeDelay;
81 try {
82 if (database.isFileLockSerialized()) {
83 wait = Constants.MIN_WRITE_DELAY;
84 database.checkpointIfRequired();
85 } else {
86 database.flush();
87 }
88 } catch (Exception e) {
89 TraceSystem traceSystem = database.getTraceSystem();
90 if (traceSystem != null) {
91 traceSystem.getTrace(Trace.DATABASE).error(e, "flush");
92 }
93 }
94 // TODO log writer: could also flush the dirty cache
95 // when there is low activity
96
97 // wait 0 mean wait forever, which is not what we want
98 wait = Math.max(wait, Constants.MIN_WRITE_DELAY);
99 synchronized (this) {
100 while (!stop && wait > 0) {
101 // wait 100 ms at a time
102 int w = Math.min(wait, 100);
103 try {
104 wait(w);
105 } catch (InterruptedException e) {
106 // ignore
107 }
108 wait -= w;
109 }
110 }
111 }
112 databaseRef = null;
113 }
114
115 /**
116 * Stop the thread. This method is called when closing the database.
117 */
118 public void stopThread() {
119 stop = true;
120 synchronized (this) {
121 notify();
122 }
123 // can't do thread.join(), because this thread might be holding
124 // a lock that the writer thread is waiting for
125 }
126
127 /**
128 * Start the thread. This method is called after opening the database
129 * (to avoid deadlocks)
130 */
131 public void startThread() {
132 thread.start();
133 thread = null;
134 }
135
136 }
137