/** * Writes out the specified Row. Will write only the Nodes or both Nodes and table row data * depending on what is not already persisted to disk. */ private void saveRow(CachedObject row) throws IOException { setFileModified(); rowOut.reset(); row.write(rowOut); dataFile.seek((long) row.getPos() * cacheFileScale); dataFile.write(rowOut.getOutputStream().getBuffer(), 0, rowOut.getOutputStream().size()); }
protected boolean readObject(int pos) throws IOException { dataFile.seek((long) pos * cacheFileScale); int size = dataFile.readInt(); rowIn.resetRow(pos, size); dataFile.read(rowIn.getBuffer(), 4, size - 4); return true; }
/** * Parameter write indicates either an orderly close, or a fast close without backup. * * <p>When false, just closes the file. * * <p>When true, writes out all cached rows that have been modified and the free position pointer * for the *.data file and then closes the file. */ public void close(boolean write) throws HsqlException { try { if (cacheReadonly) { dataFile.close(); return; } StopWatch sw = new StopWatch(); if (write) { cache.saveAll(); Trace.printSystemOut("saveAll: " + sw.elapsedTime()); // set empty dataFile.seek(LONG_EMPTY_SIZE); dataFile.writeLong(freeBlocks.getLostBlocksSize()); // set end dataFile.seek(LONG_FREE_POS_POS); dataFile.writeLong(fileFreePosition); // set saved flag; dataFile.seek(FLAGS_POS); int flag = BitMap.set(0, FLAG_ISSAVED); if (hasRowInfo) { flag = BitMap.set(flag, FLAG_ROWINFO); } dataFile.writeInt(flag); // dataFile.seek(fileFreePosition); Trace.printSystemOut("pos and flags: " + sw.elapsedTime()); } if (dataFile != null) { dataFile.close(); dataFile = null; Trace.printSystemOut("close: " + sw.elapsedTime()); } boolean empty = fileFreePosition == INITIAL_FREE_POS; if (empty) { fa.removeElement(fileName); fa.removeElement(backupFileName); } } catch (Exception e) { database.logger.appLog.logContext(e); throw Trace.error(Trace.FILE_IO_ERROR, Trace.DataFileCache_close, new Object[] {e, fileName}); } }
protected synchronized RowInputInterface readObject(int pos) throws IOException { dataFile.seek((long) pos * cacheFileScale); int size = dataFile.readInt(); rowIn.resetRow(pos, size); dataFile.read(rowIn.getBuffer(), 4, size - 4); return rowIn; }
protected void setFileModified() throws IOException { if (!fileModified) { // unset saved flag; dataFile.seek(FLAGS_POS); int flag = BitMap.set(0, FLAG_ISSAVED); if (hasRowInfo) { flag = BitMap.set(flag, FLAG_ROWINFO); } dataFile.writeInt(flag); fileModified = true; } }
protected int readSize(int pos) throws IOException { dataFile.seek((long) pos * cacheFileScale); return dataFile.readInt(); }
/** Writes out all the rows to a new file without fragmentation. */ public void defrag() throws HsqlException { if (cacheReadonly) { return; } if (fileFreePosition == INITIAL_FREE_POS) { return; } try { boolean wasNio = dataFile.wasNio(); DataFileDefrag dfd = new DataFileDefrag(database, this, fileName); dfd.process(); close(false); Trace.printSystemOut("closed old cache"); // first attemp to delete fa.removeElement(fileName); if (wasNio) { System.gc(); if (fa.isStreamElement(fileName)) { fa.removeElement(fileName); if (fa.isStreamElement(fileName)) { fa.renameElement(fileName, fileName + ".old"); File oldfile = new File(fileName + ".old"); FileUtil.deleteOnExit(oldfile); } } } // [email protected] - change to file access api fa.renameElement(fileName + ".new", fileName); backup(); database .getProperties() .setProperty("hsqldb.cache_version", HsqlDatabaseProperties.VERSION_STRING_1_7_0); database.getProperties().save(); initParams(); cache = new Cache(this); open(cacheReadonly); dfd.updateTableIndexRoots(); Trace.printSystemOut("opened cache"); } catch (Exception e) { database.logger.appLog.logContext(e); throw new HsqlException(e, Trace.getMessage(Trace.GENERAL_IO_ERROR), Trace.GENERAL_IO_ERROR); /* Trace.error(Trace.FILE_IO_ERROR, Trace.DataFileCache_defrag, new Object[] { e, fileName }); */ } }
/** * Opens the *.data file for this cache, setting the variables that allow access to the particular * database version of the *.data file. */ public void open(boolean readonly) throws HsqlException { fileFreePosition = 0; try { boolean preexists = database.isFilesInJar(); long freesize = 0; if (!preexists && fa.isStreamElement(fileName)) { if (database.isStoredFileAccess()) { preexists = true; } else { // discard "empty" databases File f = new File(fileName); preexists = f.length() > INITIAL_FREE_POS; } } if (preexists) { String version = database.getProperties().getProperty(HsqlDatabaseProperties.hsqldb_cache_version); boolean v17 = HsqlDatabaseProperties.VERSION_STRING_1_7_0.equals(version); // for later versions boolean v18 = HsqlDatabaseProperties.VERSION_STRING_1_8_0.equals(version); if (!v17) { throw Trace.error(Trace.WRONG_DATABASE_FILE_VERSION); } } boolean isNio = database.getProperties().isPropertyTrue("hsqldb.nio_data_file"); int fileType = isNio ? ScaledRAFile.DATA_FILE_NIO : ScaledRAFile.DATA_FILE_RAF; if (database.isFilesInJar()) { fileType = ScaledRAFile.DATA_FILE_JAR; } // [email protected] - change to file access api String cname = database.getURLProperties().getProperty("storage_class_name"); String skey = database.getURLProperties().getProperty("storage_key"); dataFile = ScaledRAFile.newScaledRAFile(fileName, readonly, fileType, cname, skey); if (preexists) { dataFile.seek(FLAGS_POS); int flags = dataFile.readInt(); hasRowInfo = BitMap.isSet(flags, FLAG_ROWINFO); dataFile.seek(LONG_EMPTY_SIZE); freesize = dataFile.readLong(); dataFile.seek(LONG_FREE_POS_POS); fileFreePosition = dataFile.readLong(); if (fileFreePosition < INITIAL_FREE_POS) { fileFreePosition = INITIAL_FREE_POS; } } else { fileFreePosition = INITIAL_FREE_POS; } resetBuffers(); fileModified = false; freeBlocks = new DataFileBlockManager(FREE_BLOCKS_COUNT, cacheFileScale, freesize); } catch (Exception e) { database.logger.appLog.logContext(e); close(false); throw Trace.error(Trace.FILE_IO_ERROR, Trace.DataFileCache_open, new Object[] {e, fileName}); } }
/** * Parameter write indicates either an orderly close, or a fast close without backup. * * <p>When false, just closes the file. * * <p>When true, writes out all cached rows that have been modified and the free position pointer * for the *.data file and then closes the file. */ public void close(boolean write) throws HsqlException { SimpleLog appLog = database.logger.appLog; try { if (cacheReadonly) { if (dataFile != null) { dataFile.close(); } return; } StopWatch sw = new StopWatch(); appLog.sendLine(SimpleLog.LOG_NORMAL, "DataFileCache.close(" + write + ") : start"); if (write) { cache.saveAll(); Trace.printSystemOut("saveAll: " + sw.elapsedTime()); appLog.sendLine(SimpleLog.LOG_NORMAL, "DataFileCache.close() : save data"); if (fileModified || freeBlocks.isModified()) { // set empty dataFile.seek(LONG_EMPTY_SIZE); dataFile.writeLong(freeBlocks.getLostBlocksSize()); // set end dataFile.seek(LONG_FREE_POS_POS); dataFile.writeLong(fileFreePosition); // set saved flag; dataFile.seek(FLAGS_POS); int flag = BitMap.set(0, FLAG_ISSAVED); if (hasRowInfo) { flag = BitMap.set(flag, FLAG_ROWINFO); } dataFile.writeInt(flag); appLog.sendLine(SimpleLog.LOG_NORMAL, "DataFileCache.close() : flags"); // if (dataFile.length() != fileFreePosition) { dataFile.seek(fileFreePosition); } appLog.sendLine(SimpleLog.LOG_NORMAL, "DataFileCache.close() : seek end"); Trace.printSystemOut("pos and flags: " + sw.elapsedTime()); } } if (dataFile != null) { dataFile.close(); appLog.sendLine(SimpleLog.LOG_NORMAL, "DataFileCache.close() : close"); dataFile = null; Trace.printSystemOut("close: " + sw.elapsedTime()); } boolean empty = fileFreePosition == INITIAL_FREE_POS; if (empty) { fa.removeElement(fileName); fa.removeElement(backupFileName); } } catch (Throwable e) { appLog.logContext(e); throw Trace.error(Trace.FILE_IO_ERROR, Trace.DataFileCache_close, new Object[] {e, fileName}); } }
void process() throws IOException { boolean complete = false; Error.printSystemOut("Defrag Transfer begins"); transactionRowLookup = database.txManager.getTransactionIDList(); HsqlArrayList allTables = database.schemaManager.getAllTables(); rootsList = new int[allTables.size()][]; Storage dest = null; try { OutputStream fos = database.logger.getFileAccess().openOutputStreamElement(dataFileName + ".new"); fileStreamOut = new BufferedOutputStream(fos, 1 << 12); for (int i = 0; i < DataFileCache.INITIAL_FREE_POS; i++) { fileStreamOut.write(0); } fileOffset = DataFileCache.INITIAL_FREE_POS; for (int i = 0, tSize = allTables.size(); i < tSize; i++) { Table t = (Table) allTables.get(i); if (t.getTableType() == TableBase.CACHED_TABLE) { int[] rootsArray = writeTableToDataFile(t); rootsList[i] = rootsArray; } else { rootsList[i] = null; } Error.printSystemOut(t.getName().name + " complete"); } writeTransactionRows(); fileStreamOut.flush(); fileStreamOut.close(); fileStreamOut = null; // write out the end of file position dest = ScaledRAFile.newScaledRAFile( database, dataFileName + ".new", false, ScaledRAFile.DATA_FILE_RAF, database .getURLProperties() .getProperty(HsqlDatabaseProperties.url_storage_class_name), database.getURLProperties().getProperty(HsqlDatabaseProperties.url_storage_key)); dest.seek(DataFileCache.LONG_FREE_POS_POS); dest.writeLong(fileOffset); // set shadowed flag; int flags = 0; if (database.logger.propIncrementBackup) { flags = BitMap.set(flags, DataFileCache.FLAG_ISSHADOWED); } flags = BitMap.set(flags, DataFileCache.FLAG_190); flags = BitMap.set(flags, DataFileCache.FLAG_ISSAVED); dest.seek(DataFileCache.FLAGS_POS); dest.writeInt(flags); dest.close(); dest = null; for (int i = 0, size = rootsList.length; i < size; i++) { int[] roots = rootsList[i]; if (roots != null) { Error.printSystemOut(org.hsqldb.lib.StringUtil.getList(roots, ",", "")); } } complete = true; } catch (IOException e) { throw Error.error(ErrorCode.FILE_IO_ERROR, dataFileName + ".new"); } catch (OutOfMemoryError e) { throw Error.error(ErrorCode.OUT_OF_MEMORY); } finally { if (fileStreamOut != null) { fileStreamOut.close(); } if (dest != null) { dest.close(); } if (!complete) { database.logger.getFileAccess().removeElement(dataFileName + ".new"); } } // Error.printSystemOut("Transfer complete: ", stopw.elapsedTime()); }