EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.store]

COVERAGE SUMMARY FOR SOURCE FILE [WriterThread.java]

nameclass, %method, %block, %line, %
WriterThread.java100% (1/1)83%  (5/6)76%  (116/152)73%  (35.1/48)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class WriterThread100% (1/1)83%  (5/6)76%  (116/152)73%  (35.1/48)
setWriteDelay (int): void 0%   (0/1)0%   (0/4)0%   (0/2)
run (): void 100% (1/1)69%  (54/78)68%  (18.4/27)
stopThread (): void 100% (1/1)72%  (13/18)94%  (4.7/5)
create (Database, int): WriterThread 100% (1/1)91%  (30/33)71%  (5/7)
WriterThread (Database, int): void 100% (1/1)100% (12/12)100% (4/4)
startThread (): void 100% (1/1)100% (7/7)100% (3/3)

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 */
6package org.h2.store;
7 
8import java.lang.ref.WeakReference;
9import java.security.AccessControlException;
10import org.h2.Driver;
11import org.h2.engine.Constants;
12import org.h2.engine.Database;
13import org.h2.message.Trace;
14import org.h2.message.TraceSystem;
15 
16/**
17 * The writer thread is responsible to flush the transaction transaction log
18 * from time to time.
19 */
20public class WriterThread implements Runnable {
21 
22    /**
23     * The reference to the database.
24     *
25     * Thread objects are not garbage collected
26     * until they returned from the run() method
27     * (even if they where never started)
28     * so if the connection was not closed,
29     * the database object cannot get reclaimed
30     * by the garbage collector if we use a hard reference.
31     */
32    private volatile WeakReference<Database> databaseRef;
33 
34    private int writeDelay;
35    private Thread thread;
36    private volatile boolean stop;
37 
38    private WriterThread(Database database, int writeDelay) {
39        this.databaseRef = new WeakReference<Database>(database);
40        this.writeDelay = writeDelay;
41    }
42 
43    /**
44     * Change the write delay
45     *
46     * @param writeDelay the new write delay
47     */
48    public void setWriteDelay(int writeDelay) {
49        this.writeDelay = writeDelay;
50    }
51 
52    /**
53     * Create and start a new writer thread for the given database. If the
54     * thread can't be created, this method returns null.
55     *
56     * @param database the database
57     * @param writeDelay the delay
58     * @return the writer thread object or null
59     */
60    public static WriterThread create(Database database, int writeDelay) {
61        try {
62            WriterThread writer = new WriterThread(database, writeDelay);
63            writer.thread = new Thread(writer, "H2 Log Writer " + database.getShortName());
64            Driver.setThreadContextClassLoader(writer.thread);
65            writer.thread.setDaemon(true);
66            return writer;
67        } catch (AccessControlException e) {
68            // // Google App Engine does not allow threads
69            return null;
70        }
71    }
72 
73    @Override
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 
95            // wait 0 mean wait forever, which is not what we want
96            wait = Math.max(wait, Constants.MIN_WRITE_DELAY);
97            synchronized (this) {
98                while (!stop && wait > 0) {
99                    // wait 100 ms at a time
100                    int w = Math.min(wait, 100);
101                    try {
102                        wait(w);
103                    } catch (InterruptedException e) {
104                        // ignore
105                    }
106                    wait -= w;
107                }
108            }
109        }
110        databaseRef = null;
111    }
112 
113    /**
114     * Stop the thread. This method is called when closing the database.
115     */
116    public void stopThread() {
117        stop = true;
118        synchronized (this) {
119            notify();
120        }
121        // can't do thread.join(), because this thread might be holding
122        // a lock that the writer thread is waiting for
123    }
124 
125    /**
126     * Start the thread. This method is called after opening the database
127     * (to avoid deadlocks)
128     */
129    public void startThread() {
130        thread.start();
131        thread = null;
132    }
133 
134}

[all classes][org.h2.store]
EMMA 2.0.5312 (C) Vladimir Roubtsov