1 /*******************************************************************************
2 * Copyright (c) 2012, 2014 Ericsson
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
6 * All rights reserved. This program and the accompanying materials are
7 * made available under the terms of the Eclipse Public License v1.0 which
8 * accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.internal
.tmf
.core
.statesystem
.backends
.historytree
;
16 import java
.io
.FileInputStream
;
17 import java
.io
.FileOutputStream
;
18 import java
.io
.IOException
;
19 import java
.nio
.channels
.ClosedChannelException
;
20 import java
.nio
.channels
.FileChannel
;
23 * This class abstracts inputs/outputs of the HistoryTree nodes.
25 * It contains all the methods and descriptors to handle reading/writing nodes
26 * to the tree-file on disk and all the caching mechanisms.
28 * This abstraction is mainly for code isolation/clarification purposes.
29 * Every HistoryTree must contain 1 and only 1 HT_IO element.
31 * @author Alexandre Montplaisir
35 /* Configuration of the History Tree */
36 private final HTConfig fConfig
;
38 /* Fields related to the file I/O */
39 private final FileInputStream fis
;
40 private final FileOutputStream fos
;
41 private final FileChannel fcIn
;
42 private final FileChannel fcOut
;
44 // TODO test/benchmark optimal cache size
45 private final int CACHE_SIZE
= 256;
46 private final HTNode fNodeCache
[] = new HTNode
[CACHE_SIZE
];
49 * Standard constructor
52 * The configuration object for the StateHistoryTree
54 * Flag indicating that the file must be created from scratch
57 * An exception can be thrown when file cannot be accessed
59 public HT_IO(HTConfig config
, boolean newFile
) throws IOException
{
62 File historyTreeFile
= config
.getStateFile();
64 boolean success1
= true;
65 /* Create a new empty History Tree file */
66 if (historyTreeFile
.exists()) {
67 success1
= historyTreeFile
.delete();
69 boolean success2
= historyTreeFile
.createNewFile();
70 if (!(success1
&& success2
)) {
71 /* It seems we do not have permission to create the new file */
72 throw new IOException("Cannot create new file at " + //$NON-NLS-1$
73 historyTreeFile
.getName());
75 fis
= new FileInputStream(historyTreeFile
);
76 fos
= new FileOutputStream(historyTreeFile
, false);
79 * We want to open an existing file, make sure we don't squash the
80 * existing content when opening the fos!
82 this.fis
= new FileInputStream(historyTreeFile
);
83 this.fos
= new FileOutputStream(historyTreeFile
, true);
85 this.fcIn
= fis
.getChannel();
86 this.fcOut
= fos
.getChannel();
90 * Read a node from the file on disk.
93 * The sequence number of the node to read.
94 * @return The object representing the node
95 * @throws ClosedChannelException
96 * Usually happens because the file was closed while we were
97 * reading. Instead of using a big reader-writer lock, we'll
98 * just catch this exception.
100 public synchronized HTNode
readNode(int seqNumber
) throws ClosedChannelException
{
101 /* Do a cache lookup */
102 int offset
= seqNumber
& (CACHE_SIZE
- 1);
103 HTNode readNode
= fNodeCache
[offset
];
104 if (readNode
!= null && readNode
.getSequenceNumber() == seqNumber
) {
110 seekFCToNodePos(fcIn
, seqNumber
);
111 readNode
= HTNode
.readNode(fConfig
, fcIn
);
113 /* Put the node in the cache. */
114 fNodeCache
[offset
] = readNode
;
116 } catch (ClosedChannelException e
) {
118 } catch (IOException e
) {
119 /* Other types of IOExceptions shouldn't happen at this point though */
125 public synchronized void writeNode(HTNode node
) {
127 /* Insert the node into the cache. */
128 int seqNumber
= node
.getSequenceNumber();
129 int offset
= seqNumber
& (CACHE_SIZE
- 1);
130 fNodeCache
[offset
] = node
;
132 /* Position ourselves at the start of the node and write it */
133 seekFCToNodePos(fcOut
, seqNumber
);
134 node
.writeSelf(fcOut
);
135 } catch (IOException e
) {
136 /* If we were able to open the file, we should be fine now... */
141 public FileChannel
getFcOut() {
145 public FileInputStream
supplyATReader(int nodeOffset
) {
148 * Position ourselves at the start of the Mapping section in the
149 * file (which is right after the Blocks)
151 seekFCToNodePos(fcIn
, nodeOffset
);
152 } catch (IOException e
) {
158 public synchronized void closeFile() {
162 } catch (IOException e
) {
167 public synchronized void deleteFile() {
170 File historyTreeFile
= fConfig
.getStateFile();
171 if (!historyTreeFile
.delete()) {
172 /* We didn't succeed in deleting the file */
178 * Seek the given FileChannel to the position corresponding to the node that
181 * @param fc the channel to seek
182 * @param seqNumber the node sequence number to seek the channel to
183 * @throws IOException
185 private void seekFCToNodePos(FileChannel fc
, int seqNumber
)
188 * Cast to (long) is needed to make sure the result is a long too and
189 * doesn't get truncated
191 fc
.position(HistoryTree
.TREE_HEADER_SIZE
192 + ((long) seqNumber
) * fConfig
.getBlockSize());
This page took 0.037216 seconds and 6 git commands to generate.