#57975: Number of file descriptors held by MDR is now limited to 200.
1.1 --- a/mdr/src/org/netbeans/mdr/persistence/btreeimpl/btreestorage/FileCache.java Fri Aug 19 14:51:36 2005 +0000
1.2 +++ b/mdr/src/org/netbeans/mdr/persistence/btreeimpl/btreestorage/FileCache.java Fri Aug 19 23:12:57 2005 +0000
1.3 @@ -16,6 +16,7 @@
1.4 import java.util.*;
1.5
1.6 import org.netbeans.mdr.persistence.*;
1.7 +import org.netbeans.mdr.util.Logger;
1.8
1.9 /**
1.10 * FileCache provides transactional cached access to a set of files.
1.11 @@ -27,9 +28,7 @@
1.12 */
1.13 public class FileCache {
1.14
1.15 - /* files contained in the cache */
1.16 - private RandomAccessFile files[];
1.17 -
1.18 + private String[] fileNames;
1.19 /* sizes of files contained in the cache. */
1.20 private int fileSize[];
1.21
1.22 @@ -78,6 +77,42 @@
1.23 /* A list of objects to notify before comitting */
1.24 private ArrayList toNotify;
1.25
1.26 + private static final int MAX_FILES = 200;
1.27 + private static final Map OPEN_FILES_CACHE = new LinkedHashMap(MAX_FILES * 2, .5f, true) {
1.28 + protected boolean removeEldestEntry(Map.Entry eldest) {
1.29 + if (size() > MAX_FILES) {
1.30 + RandomAccessFile file = (RandomAccessFile) eldest.getValue();
1.31 + try {
1.32 + file.close();
1.33 + } catch (IOException e) {
1.34 + Logger.getDefault().notify(e);
1.35 + }
1.36 + return true;
1.37 + }
1.38 + return false;
1.39 + }
1.40 + };
1.41 +
1.42 + static void closeFile(String fileName) throws IOException {
1.43 + RandomAccessFile file;
1.44 + synchronized (FileCache.OPEN_FILES_CACHE) {
1.45 + file = (RandomAccessFile) FileCache.OPEN_FILES_CACHE.remove(fileName);
1.46 + }
1.47 + if (file != null) file.close();
1.48 + }
1.49 +
1.50 + static RandomAccessFile getFile(String fileName) throws IOException {
1.51 + RandomAccessFile result;
1.52 + synchronized (FileCache.OPEN_FILES_CACHE) {
1.53 + result = (RandomAccessFile) FileCache.OPEN_FILES_CACHE.get(fileName);
1.54 + if (result == null) {
1.55 + result = new RandomAccessFile(fileName, "rw");
1.56 + FileCache.OPEN_FILES_CACHE.put(fileName, result);
1.57 + }
1.58 + }
1.59 + return result;
1.60 + }
1.61 +
1.62 static {
1.63 pages = new ArrayList(BtreeDatabase.FILE_CACHE_SIZE);
1.64 pageHash = new HashMap();
1.65 @@ -149,16 +184,18 @@
1.66 public FileCache(String fileNames[], String baseName)
1.67 throws StorageException {
1.68
1.69 + this.fileNames = new String[fileNames.length];
1.70 boolean failure = true;
1.71 try {
1.72 try {
1.73 - files = new RandomAccessFile[fileNames.length];
1.74 + RandomAccessFile[] files = new RandomAccessFile[fileNames.length];
1.75 fileSize = new int[fileNames.length];
1.76
1.77 FileHeader tmpHeader;
1.78
1.79 for (int i = 0; i < fileNames.length; i++) {
1.80 - files[i] = new RandomAccessFile(fileNames[i], "rw");
1.81 + files[i] = getFile(fileNames[i]);
1.82 + this.fileNames[i] = fileNames[i];
1.83 }
1.84 tmpHeader = new FileHeader(files[0]);
1.85
1.86 @@ -187,11 +224,9 @@
1.87 }
1.88 finally {
1.89 if (failure) {
1.90 - if (files != null) {
1.91 - for (int i = 0; i < files.length; i++) {
1.92 - if (files[i] != null) {
1.93 - files[i].close();
1.94 - }
1.95 + for (int i = 0; i < this.fileNames.length; i++) {
1.96 + if (this.fileNames[i] != null) {
1.97 + closeFile(this.fileNames[i]);
1.98 }
1.99 }
1.100 if (log != null)
1.101 @@ -207,7 +242,15 @@
1.102
1.103 /** return the array of open files
1.104 */
1.105 - RandomAccessFile[] getFiles() {
1.106 + RandomAccessFile[] getFiles() throws IOException {
1.107 + return getFiles(fileNames);
1.108 + }
1.109 +
1.110 + static RandomAccessFile[] getFiles(String[] fileNames) throws IOException {
1.111 + RandomAccessFile[] files = new RandomAccessFile[fileNames.length];
1.112 + for (int i = 0; i < fileNames.length; i++) {
1.113 + files[i] = FileCache.getFile(fileNames[i]);
1.114 + }
1.115 return files;
1.116 }
1.117
1.118 @@ -251,8 +294,8 @@
1.119 /* close all files */
1.120 private void closeFiles() throws StorageException {
1.121 try {
1.122 - for (int i = 0; i < files.length; i++)
1.123 - files[i].close();
1.124 + for (int i = 0; i < fileNames.length; i++)
1.125 + closeFile(fileNames[i]);
1.126 log.close();
1.127 }
1.128 catch (IOException ex) {
1.129 @@ -281,7 +324,7 @@
1.130 if (inXact) {
1.131
1.132 /* update timestaps */
1.133 - for (int i = 0; i < files.length; i++) {
1.134 + for (int i = 0; i < fileNames.length; i++) {
1.135 CachedPage first = getPage(i, 0);
1.136 setWritable(first);
1.137 FileHeader.updateTime(first, newTimeStamp);
1.138 @@ -314,7 +357,7 @@
1.139
1.140 if (!instances.contains(owner)) return; // obsolete page from an old cache that was deactivated
1.141
1.142 - RandomAccessFile file = owner.files[page.key.fileIndex];
1.143 + RandomAccessFile file = getFile(owner.fileNames[page.key.fileIndex]);
1.144 file.seek(page.key.offset);
1.145 file.write(page.contents);
1.146 page.isDirty = false;
1.147 @@ -481,8 +524,9 @@
1.148 }
1.149 else {
1.150 try {
1.151 - instance.files[id.fileIndex].seek(id.offset);
1.152 - instance.files[id.fileIndex].readFully(free.contents);
1.153 + RandomAccessFile file = getFile(instance.fileNames[id.fileIndex]);
1.154 + file.seek(id.offset);
1.155 + file.readFully(free.contents);
1.156 }
1.157 catch (IOException ex) {
1.158 throw new StorageIOException(ex);
1.159 @@ -508,7 +552,7 @@
1.160
1.161 if (!inXact) {
1.162 newTimeStamp = System.currentTimeMillis();
1.163 - log.begin(files, header.timeStamp, newTimeStamp);
1.164 + log.begin(fileNames, header.timeStamp, newTimeStamp);
1.165 inXact = true;
1.166 }
1.167 log.addPageToLog(page);
1.168 @@ -532,9 +576,9 @@
1.169 */
1.170 public void dumpCache(PrintStream strm) {
1.171 strm.println("Cached files:");
1.172 - for (int i = 0; i < files.length; i++) {
1.173 + for (int i = 0; i < fileNames.length; i++) {
1.174 strm.println(
1.175 - Integer.toString(i) + ": " + files[i].toString() +
1.176 + Integer.toString(i) + ": " + fileNames[i] +
1.177 " size: " + fileSize[i]);
1.178 }
1.179 strm.println("");
2.1 --- a/mdr/src/org/netbeans/mdr/persistence/btreeimpl/btreestorage/LogFile.java Fri Aug 19 14:51:36 2005 +0000
2.2 +++ b/mdr/src/org/netbeans/mdr/persistence/btreeimpl/btreestorage/LogFile.java Fri Aug 19 23:12:57 2005 +0000
2.3 @@ -41,8 +41,8 @@
2.4 /* name of the log file */
2.5 private final String baseName;
2.6
2.7 - /* the log file */
2.8 - private RandomAccessFile file;
2.9 + /* name of the log file */
2.10 + private String name;
2.11
2.12 /* bitmaps showing which pages are currently logged */
2.13 private BitSet pageBitmaps[];
2.14 @@ -96,14 +96,20 @@
2.15 }
2.16
2.17 /* create the log file */
2.18 - private void createPhysicalLog() throws StorageException {
2.19 + private RandomAccessFile createPhysicalLog() throws StorageException {
2.20 + String name = BtreeDatabase.getFileName(baseName, BtreeDatabase.LFL);
2.21 + RandomAccessFile file = null;
2.22 try {
2.23 - file = new RandomAccessFile(BtreeDatabase.getFileName(baseName, BtreeDatabase.LFL), "rw");
2.24 + file = FileCache.getFile(name);
2.25 file.setLength(0);
2.26 - writeMap();
2.27 - }
2.28 - catch (IOException ex) {
2.29 + writeMap(file);
2.30 + return file;
2.31 + } catch (IOException ex) {
2.32 throw new StorageIOException(ex);
2.33 + } finally {
2.34 + if (file != null) {
2.35 + this.name = name;
2.36 + }
2.37 }
2.38 }
2.39
2.40 @@ -120,10 +126,9 @@
2.41 if (isPageLogged(page))
2.42 return;
2.43
2.44 - if (file == null)
2.45 - createPhysicalLog();
2.46 -
2.47 + RandomAccessFile file;
2.48 try {
2.49 + file = name == null ? createPhysicalLog() : FileCache.getFile(name);
2.50 file.seek(currentMap.nextPageOffset());
2.51 file.write(page.contents);
2.52 }
2.53 @@ -142,25 +147,24 @@
2.54 if (currentMap.isFull()) {
2.55
2.56 // map is full; need to write it
2.57 - writeMap();
2.58 + writeMap(file);
2.59 }
2.60
2.61 /* prevent from being written until log is flushed */
2.62 cache.holdForLog(page);
2.63 }
2.64
2.65 -
2.66 /* write the current map page to the log */
2.67 - private void writeMap() throws StorageException{
2.68 - flushFile();
2.69 + private void writeMap(RandomAccessFile file) throws StorageException{
2.70 + flushFile(file);
2.71 currentMap.write(file);
2.72 - flushFile();
2.73 + flushFile(file);
2.74 if (currentMap.isFull())
2.75 currentMap = new MapPage(currentMap);
2.76 }
2.77
2.78 /* sync the file to disk */
2.79 - private void flushFile() throws StorageException{
2.80 + private void flushFile(RandomAccessFile file) throws StorageException{
2.81 try {
2.82 file.getFD().sync();
2.83 }
2.84 @@ -173,8 +177,12 @@
2.85 * @exception StorageException I/O error writing the log
2.86 */
2.87 void flush() throws StorageException{
2.88 - writeMap();
2.89 - cache.logWasFlushed();
2.90 + try {
2.91 + writeMap(FileCache.getFile(name));
2.92 + cache.logWasFlushed();
2.93 + } catch (IOException e) {
2.94 + throw new StorageIOException(e);
2.95 + }
2.96 }
2.97
2.98 /** begin a new transaction
2.99 @@ -183,11 +191,17 @@
2.100 * @param long newTimeStamp the timestamp for the new transaction
2.101 * @exception StorageException I/O error accessing the files
2.102 */
2.103 - void begin(RandomAccessFile files[], long timeStamp, long newTimeStamp)
2.104 + void begin(String fileNames[], long timeStamp, long newTimeStamp)
2.105 throws StorageException {
2.106
2.107 - file = null;
2.108 + name = null;
2.109 currentMap = new MapPage(pageSize, numFiles, 0);
2.110 + RandomAccessFile files[];
2.111 + try {
2.112 + files = FileCache.getFiles(fileNames);
2.113 + } catch (IOException e) {
2.114 + throw new StorageIOException(e);
2.115 + }
2.116 currentMap.setEOFs(files);
2.117 for (int i = 0; i < numFiles; i++) {
2.118 pageBitmaps[i].xor(pageBitmaps[i]);
2.119 @@ -201,15 +215,15 @@
2.120 */
2.121 void commit() throws StorageException{
2.122 try {
2.123 - if (file != null) {
2.124 - file.close();
2.125 - (new File(BtreeDatabase.getFileName(baseName, BtreeDatabase.LFL))).delete();
2.126 + if (name != null) {
2.127 + FileCache.closeFile(name);
2.128 + new File(name).delete();
2.129 }
2.130 }
2.131 catch (IOException ex) {
2.132 throw new StorageIOException(ex);
2.133 }
2.134 - file = null;
2.135 + name = null;
2.136 afterCommitFailure =
2.137 cache.checkForForcedFailure(
2.138 "org.netbeans.mdr.persistence.btreeimpl.btreestorage.LogFile.afterCommitFailure",
2.139 @@ -221,10 +235,10 @@
2.140 */
2.141 void close() throws StorageException{
2.142 try {
2.143 - if (file != null)
2.144 - file.close();
2.145 + if (name != null) {
2.146 + FileCache.closeFile(name);
2.147 }
2.148 - catch (IOException ex) {
2.149 + } catch (IOException ex) {
2.150 throw new StorageIOException(ex);
2.151 }
2.152 }
2.153 @@ -248,7 +262,6 @@
2.154 try {
2.155 logFile = new RandomAccessFile(BtreeDatabase.getFileName(baseName, BtreeDatabase.LFL), "r");
2.156 files = cache.getFiles();
2.157 -
2.158 if (files.length != numFiles) {
2.159 throw new StorageBadRequestException(
2.160 MessageFormat.format(