@Override public void test() throws Exception { if (!SysProperties.MODIFY_ON_WRITE) { return; } deleteDb("modifyOnWrite"); String dbFile = getBaseDir() + "/modifyOnWrite.h2.db"; assertFalse(FileUtils.exists(dbFile)); Connection conn = getConnection("modifyOnWrite"); Statement stat = conn.createStatement(); stat.execute("create table test(id int)"); conn.close(); byte[] test = IOUtils.readBytesAndClose(FileUtils.newInputStream(dbFile), -1); conn = getConnection("modifyOnWrite"); stat = conn.createStatement(); ResultSet rs; rs = stat.executeQuery("select * from test"); assertFalse(rs.next()); conn.close(); assertTrue(FileUtils.exists(dbFile)); byte[] test2 = IOUtils.readBytesAndClose(FileUtils.newInputStream(dbFile), -1); assertEquals(test, test2); conn = getConnection("modifyOnWrite"); stat = conn.createStatement(); stat.execute("insert into test values(1)"); conn.close(); conn = getConnection("modifyOnWrite"); stat = conn.createStatement(); rs = stat.executeQuery("select * from test"); assertTrue(rs.next()); conn.close(); test2 = IOUtils.readBytesAndClose(FileUtils.newInputStream(dbFile), -1); assertFalse(Utils.compareSecure(test, test2)); }
private boolean openWriter() { if (printWriter == null) { try { FileUtils.createDirectories(FileUtils.getParent(fileName)); if (FileUtils.exists(fileName) && !FileUtils.canWrite(fileName)) { // read only database: don't log error if the trace file // can't be opened return false; } fileWriter = IOUtils.getBufferedWriter(FileUtils.newOutputStream(fileName, true)); printWriter = new PrintWriter(fileWriter, true); } catch (Exception e) { logWritingError(e); return false; } } return true; }
@Override public FileStore openFile(String name, String mode, boolean mustExist) { if (mustExist && !FileUtils.exists(name)) { throw DbException.get(ErrorCode.FILE_NOT_FOUND_1, name); } FileStore store; if (cipher == null) { store = FileStore.open(this, name, mode); } else { store = FileStore.open(this, name, mode, cipher, fileEncryptionKey, 0); } store.setCheckedWriting(false); try { store.init(); } catch (DbException e) { store.closeSilently(); throw e; } return store; }
/** * Get the unique and normalized database name (excluding settings). * * @return the database name */ public String getName() { if (!persistent) { return name; } if (nameNormalized == null) { if (!SysProperties.IMPLICIT_RELATIVE_PATH) { if (!FileUtils.isAbsolute(name)) { if (name.indexOf("./") < 0 && name.indexOf(".\\") < 0 && name.indexOf(":/") < 0 && name.indexOf(":\\") < 0) { // the name could start with "./", or // it could start with a prefix such as "nio:./" // for Windows, the path "\test" is not considered // absolute as the drive letter is missing, // but we consider it absolute throw DbException.get(ErrorCode.URL_RELATIVE_TO_CWD, originalURL); } } } String suffix = Constants.SUFFIX_PAGE_FILE; String n; if (FileUtils.exists(name + suffix)) { n = FileUtils.toRealPath(name + suffix); } else { suffix = Constants.SUFFIX_MV_FILE; n = FileUtils.toRealPath(name + suffix); } String fileName = FileUtils.getName(n); if (fileName.length() < suffix.length() + 1) { // 例如: 没有设置baseDir且dbName="./"时 throw DbException.get(ErrorCode.INVALID_DATABASE_NAME_1, name); } nameNormalized = n.substring(0, n.length() - suffix.length()); } return nameNormalized; }
/** * Restores database files. * * @param zipFileName the name of the backup file * @param directory the directory name * @param db the database name (null for all databases) * @throws DbException if there is an IOException */ public static void execute(String zipFileName, String directory, String db) { InputStream in = null; try { if (!FileUtils.exists(zipFileName)) { throw new IOException("File not found: " + zipFileName); } String originalDbName = null; int originalDbLen = 0; if (db != null) { originalDbName = getOriginalDbName(zipFileName, db); if (originalDbName == null) { throw new IOException("No database named " + db + " found"); } if (originalDbName.startsWith(SysProperties.FILE_SEPARATOR)) { originalDbName = originalDbName.substring(1); } originalDbLen = originalDbName.length(); } in = FileUtils.newInputStream(zipFileName); ZipInputStream zipIn = new ZipInputStream(in); while (true) { ZipEntry entry = zipIn.getNextEntry(); if (entry == null) { break; } String fileName = entry.getName(); // restoring windows backups on linux and vice versa fileName = fileName.replace('\\', SysProperties.FILE_SEPARATOR.charAt(0)); fileName = fileName.replace('/', SysProperties.FILE_SEPARATOR.charAt(0)); if (fileName.startsWith(SysProperties.FILE_SEPARATOR)) { fileName = fileName.substring(1); } boolean copy = false; if (db == null) { copy = true; } else if (fileName.startsWith(originalDbName + ".")) { fileName = db + fileName.substring(originalDbLen); copy = true; } if (copy) { OutputStream o = null; try { o = FileUtils.newOutputStream( directory + SysProperties.FILE_SEPARATOR + fileName, false); IOUtils.copy(zipIn, o); o.close(); } finally { IOUtils.closeSilently(o); } } zipIn.closeEntry(); } zipIn.closeEntry(); zipIn.close(); } catch (IOException e) { throw DbException.convertIOException(e, zipFileName); } finally { IOUtils.closeSilently(in); } }
private void testTools() throws Exception { if (config.memory) { return; } deleteDb("web"); Connection conn = getConnection("web"); conn.createStatement().execute("create table test(id int) as select 1"); conn.close(); Server server = new Server(); server.setOut(new PrintStream(new ByteArrayOutputStream())); server.runTool("-web", "-webPort", "8182", "-properties", "null", "-tcp", "-tcpPort", "9101"); try { String url = "http://localhost:8182"; WebClient client; String result; client = new WebClient(); result = client.get(url); client.readSessionId(result); result = client.get(url, "tools.jsp"); FileUtils.delete(getBaseDir() + "/backup.zip"); result = client.get( url, "tools.do?tool=Backup&args=-dir," + getBaseDir() + ",-db,web,-file," + getBaseDir() + "/backup.zip"); deleteDb("web"); assertTrue(FileUtils.exists(getBaseDir() + "/backup.zip")); result = client.get(url, "tools.do?tool=DeleteDbFiles&args=-dir," + getBaseDir() + ",-db,web"); assertFalse(FileUtils.exists(getBaseDir() + "/web.h2.db")); result = client.get( url, "tools.do?tool=Restore&args=-dir," + getBaseDir() + ",-db,web,-file," + getBaseDir() + "/backup.zip"); assertTrue(FileUtils.exists(getBaseDir() + "/web.h2.db")); FileUtils.delete(getBaseDir() + "/web.h2.sql"); FileUtils.delete(getBaseDir() + "/backup.zip"); result = client.get(url, "tools.do?tool=Recover&args=-dir," + getBaseDir() + ",-db,web"); assertTrue(FileUtils.exists(getBaseDir() + "/web.h2.sql")); FileUtils.delete(getBaseDir() + "/web.h2.sql"); result = client.get( url, "tools.do?tool=RunScript&args=-script," + getBaseDir() + "/web.h2.sql,-url," + getURL("web", true) + ",-user," + getUser() + ",-password," + getPassword()); FileUtils.delete(getBaseDir() + "/web.h2.sql"); assertTrue(FileUtils.exists(getBaseDir() + "/web.h2.db")); deleteDb("web"); } finally { server.shutdown(); } }
private void testStopWhileCommitting() throws Exception { String fileName = getBaseDir() + "/testStopWhileCommitting.h3"; FileUtils.delete(fileName); Random r = new Random(0); for (int i = 0; i < 10; ) { MVStore s; TransactionStore ts; Transaction tx; TransactionMap<Integer, String> m; s = MVStore.open(fileName); ts = new TransactionStore(s); tx = ts.begin(); s.setReuseSpace(false); m = tx.openMap("test"); final String value = "x" + i; for (int j = 0; j < 1000; j++) { m.put(j, value); } final AtomicInteger state = new AtomicInteger(); final MVStore store = s; final MVMap<Integer, String> other = s.openMap("other"); Task task = new Task() { @Override public void call() throws Exception { for (int i = 0; !stop; i++) { state.set(i); other.put(i, value); store.commit(); } } }; task.execute(); // wait for the task to start while (state.get() < 1) { Thread.yield(); } // commit while writing in the task tx.commit(); // wait for the task to stop task.get(); store.close(); s = MVStore.open(fileName); // roll back a bit, until we have some undo log entries assertTrue(s.hasMap("undoLog")); for (int back = 0; back < 100; back++) { int minus = r.nextInt(10); s.rollbackTo(Math.max(0, s.getCurrentVersion() - minus)); MVMap<?, ?> undo = s.openMap("undoLog"); if (undo.size() > 0) { break; } } ts = new TransactionStore(s); List<Transaction> list = ts.getOpenTransactions(); if (list.size() != 0) { tx = list.get(0); if (tx.getStatus() == Transaction.STATUS_COMMITTING) { i++; } } s.close(); FileUtils.delete(fileName); assertFalse(FileUtils.exists(fileName)); } }