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

COVERAGE SUMMARY FOR SOURCE FILE [RecoverTester.java]

nameclass, %method, %block, %line, %
RecoverTester.java100% (1/1)0%   (0/6)0%   (0/477)0%   (0/102)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class RecoverTester100% (1/1)0%   (0/6)0%   (0/477)0%   (0/102)
RecoverTester (): void 0%   (0/1)0%   (0/29)0%   (0/6)
getInstance (): RecoverTester 0%   (0/1)0%   (0/8)0%   (0/3)
init (String): void 0%   (0/1)0%   (0/12)0%   (0/5)
log (int, String, byte [], long): void 0%   (0/1)0%   (0/86)0%   (0/21)
setTestEvery (int): void 0%   (0/1)0%   (0/4)0%   (0/2)
testDatabase (String, PrintWriter): void 0%   (0/1)0%   (0/338)0%   (0/65)

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.io.IOException;
9import java.io.OutputStreamWriter;
10import java.io.PrintWriter;
11import java.sql.SQLException;
12import java.util.HashSet;
13import java.util.Properties;
14 
15import org.h2.api.ErrorCode;
16import org.h2.engine.ConnectionInfo;
17import org.h2.engine.Constants;
18import org.h2.engine.Database;
19import org.h2.engine.Session;
20import org.h2.message.DbException;
21import org.h2.store.fs.FilePathRec;
22import org.h2.store.fs.FileUtils;
23import org.h2.store.fs.Recorder;
24import org.h2.tools.Recover;
25import org.h2.util.IOUtils;
26import org.h2.util.New;
27import org.h2.util.StringUtils;
28import org.h2.util.Utils;
29 
30/**
31 * A tool that simulates a crash while writing to the database, and then
32 * verifies the database doesn't get corrupt.
33 */
34public class RecoverTester implements Recorder {
35 
36    private static RecoverTester instance;
37 
38    private String testDatabase = "memFS:reopen";
39    private int writeCount = Utils.getProperty("h2.recoverTestOffset", 0);
40    private int testEvery = Utils.getProperty("h2.recoverTest", 64);
41    private final long maxFileSize = Utils.getProperty(
42            "h2.recoverTestMaxFileSize", Integer.MAX_VALUE) * 1024L * 1024;
43    private int verifyCount;
44    private final HashSet<String> knownErrors = New.hashSet();
45    private volatile boolean testing;
46 
47    /**
48     * Initialize the recover test.
49     *
50     * @param recoverTest the value of the recover test parameter
51     */
52    public static synchronized void init(String recoverTest) {
53        RecoverTester tester = RecoverTester.getInstance();
54        if (StringUtils.isNumber(recoverTest)) {
55            tester.setTestEvery(Integer.parseInt(recoverTest));
56        }
57        FilePathRec.setRecorder(tester);
58    }
59 
60    public static synchronized RecoverTester getInstance() {
61        if (instance == null) {
62            instance = new RecoverTester();
63        }
64        return instance;
65    }
66 
67    @Override
68    public void log(int op, String fileName, byte[] data, long x) {
69        if (op != Recorder.WRITE && op != Recorder.TRUNCATE) {
70            return;
71        }
72        if (!fileName.endsWith(Constants.SUFFIX_PAGE_FILE) &&
73                !fileName.endsWith(Constants.SUFFIX_MV_FILE)) {
74            return;
75        }
76        writeCount++;
77        if ((writeCount % testEvery) != 0) {
78            return;
79        }
80        if (FileUtils.size(fileName) > maxFileSize) {
81            // System.out.println(fileName + " " + IOUtils.length(fileName));
82            return;
83        }
84        if (testing) {
85            // avoid deadlocks
86            return;
87        }
88        testing = true;
89        PrintWriter out = null;
90        try {
91            out = new PrintWriter(
92                    new OutputStreamWriter(
93                    FileUtils.newOutputStream(fileName + ".log", true)));
94            testDatabase(fileName, out);
95        } catch (IOException e) {
96            throw DbException.convertIOException(e, null);
97        } finally {
98            IOUtils.closeSilently(out);
99            testing = false;
100        }
101    }
102 
103    private synchronized void testDatabase(String fileName, PrintWriter out) {
104        out.println("+ write #" + writeCount + " verify #" + verifyCount);
105        try {
106            IOUtils.copyFiles(fileName, testDatabase + Constants.SUFFIX_PAGE_FILE);
107            String mvFileName = fileName.substring(0, fileName.length() -
108                    Constants.SUFFIX_PAGE_FILE.length()) +
109                    Constants.SUFFIX_MV_FILE;
110            if (FileUtils.exists(mvFileName)) {
111                IOUtils.copyFiles(mvFileName, testDatabase + Constants.SUFFIX_MV_FILE);
112            }
113            verifyCount++;
114            // avoid using the Engine class to avoid deadlocks
115            Properties p = new Properties();
116            p.setProperty("user", "");
117            p.setProperty("password", "");
118            ConnectionInfo ci = new ConnectionInfo("jdbc:h2:" + testDatabase +
119                    ";FILE_LOCK=NO;TRACE_LEVEL_FILE=0", p);
120            Database database = new Database(ci, null);
121            // close the database
122            Session sysSession = database.getSystemSession();
123            sysSession.prepare("script to '" + testDatabase + ".sql'").query(0);
124            sysSession.prepare("shutdown immediately").update();
125            database.removeSession(null);
126            // everything OK - return
127            return;
128        } catch (DbException e) {
129            SQLException e2 = DbException.toSQLException(e);
130            int errorCode = e2.getErrorCode();
131            if (errorCode == ErrorCode.WRONG_USER_OR_PASSWORD) {
132                return;
133            } else if (errorCode == ErrorCode.FILE_ENCRYPTION_ERROR_1) {
134                return;
135            }
136            e.printStackTrace(System.out);
137        } catch (Exception e) {
138            // failed
139            int errorCode = 0;
140            if (e instanceof SQLException) {
141                errorCode = ((SQLException) e).getErrorCode();
142            }
143            if (errorCode == ErrorCode.WRONG_USER_OR_PASSWORD) {
144                return;
145            } else if (errorCode == ErrorCode.FILE_ENCRYPTION_ERROR_1) {
146                return;
147            }
148            e.printStackTrace(System.out);
149        }
150        out.println("begin ------------------------------ " + writeCount);
151        try {
152            Recover.execute(fileName.substring(0, fileName.lastIndexOf('/')), null);
153        } catch (SQLException e) {
154            // ignore
155        }
156        testDatabase += "X";
157        try {
158            IOUtils.copyFiles(fileName, testDatabase + Constants.SUFFIX_PAGE_FILE);
159            // avoid using the Engine class to avoid deadlocks
160            Properties p = new Properties();
161            ConnectionInfo ci = new ConnectionInfo("jdbc:h2:" +
162                        testDatabase + ";FILE_LOCK=NO", p);
163            Database database = new Database(ci, null);
164            // close the database
165            database.removeSession(null);
166        } catch (Exception e) {
167            int errorCode = 0;
168            if (e instanceof DbException) {
169                e = ((DbException) e).getSQLException();
170                errorCode = ((SQLException) e).getErrorCode();
171            }
172            if (errorCode == ErrorCode.WRONG_USER_OR_PASSWORD) {
173                return;
174            } else if (errorCode == ErrorCode.FILE_ENCRYPTION_ERROR_1) {
175                return;
176            }
177            StringBuilder buff = new StringBuilder();
178            StackTraceElement[] list = e.getStackTrace();
179            for (int i = 0; i < 10 && i < list.length; i++) {
180                buff.append(list[i].toString()).append('\n');
181            }
182            String s = buff.toString();
183            if (!knownErrors.contains(s)) {
184                out.println(writeCount + " code: " + errorCode + " " + e.toString());
185                e.printStackTrace(System.out);
186                knownErrors.add(s);
187            } else {
188                out.println(writeCount + " code: " + errorCode);
189            }
190        }
191    }
192 
193    public void setTestEvery(int testEvery) {
194        this.testEvery = testEvery;
195    }
196 
197}

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