1 /*******************************************************************************
2 * Copyright (c) 2012 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 exists mainly for code isolation/clarification purposes. It
24 * contains all the methods and descriptors to handle reading/writing to the
25 * tree-file on disk and all the caching mechanisms. Every HistoryTree should
26 * contain 1 and only 1 HT_IO element.
33 /* reference to the tree to which this IO-object belongs */
34 private final HistoryTree tree
;
36 /* Fields related to the file I/O */
37 private final File historyTreeFile
;
38 private final FileInputStream fis
;
39 private final FileOutputStream fos
;
40 private final FileChannel fcIn
;
41 private final FileChannel fcOut
;
44 * Standard constructor
48 * Are we creating a new file from scratch?
51 HT_IO(HistoryTree tree
, boolean newFile
) throws IOException
{
53 historyTreeFile
= tree
.config
.stateFile
;
54 boolean success1
= true, success2
;
57 /* Create a new empty History Tree file */
58 if (historyTreeFile
.exists()) {
59 success1
= historyTreeFile
.delete();
61 success2
= historyTreeFile
.createNewFile();
62 if (!(success1
&& success2
)) {
63 /* It seems we do not have permission to create the new file */
64 throw new IOException("Cannot create new file at " + //$NON-NLS-1$
65 historyTreeFile
.getName());
67 fis
= new FileInputStream(historyTreeFile
);
68 fos
= new FileOutputStream(historyTreeFile
, false);
71 * We want to open an existing file, make sure we don't squash the
72 * existing content when opening the fos!
74 this.fis
= new FileInputStream(historyTreeFile
);
75 this.fos
= new FileOutputStream(historyTreeFile
, true);
77 this.fcIn
= fis
.getChannel();
78 this.fcOut
= fos
.getChannel();
82 * Generic "read node" method, which checks if the node is in memory first,
83 * and if it's not it goes to disk to retrieve it.
86 * Sequence number of the node we want
87 * @return The wanted node in object form
88 * @throws ClosedChannelException
89 * If the channel was closed before we could read
91 HTNode
readNode(int seqNumber
) throws ClosedChannelException
{
92 HTNode node
= readNodeFromMemory(seqNumber
);
94 return readNodeFromDisk(seqNumber
);
99 private HTNode
readNodeFromMemory(int seqNumber
) {
100 for (HTNode node
: tree
.latestBranch
) {
101 if (node
.getSequenceNumber() == seqNumber
) {
109 * This method here isn't private, if we know for sure the node cannot be in
110 * memory it's a bit faster to use this directly (when opening a file from
113 * @throws ClosedChannelException
114 * Usually happens because the file was closed while we were
115 * reading. Instead of using a big reader-writer lock, we'll
116 * just catch this exception.
118 synchronized HTNode
readNodeFromDisk(int seqNumber
) throws ClosedChannelException
{
121 seekFCToNodePos(fcIn
, seqNumber
);
122 readNode
= HTNode
.readNode(tree
, fcIn
);
124 } catch (ClosedChannelException e
) {
126 } catch (IOException e
) {
127 /* Other types of IOExceptions shouldn't happen at this point though */
133 void writeNode(HTNode node
) {
135 /* Position ourselves at the start of the node and write it */
136 seekFCToNodePos(fcOut
, node
.getSequenceNumber());
137 node
.writeSelf(fcOut
);
138 } catch (IOException e
) {
139 /* If we were able to open the file, we should be fine now... */
144 FileChannel
getFcOut() {
148 FileInputStream
supplyATReader() {
151 * Position ourselves at the start of the Mapping section in the
152 * file (which is right after the Blocks)
154 seekFCToNodePos(fcIn
, tree
.getNodeCount());
155 } catch (IOException e
) {
161 File
supplyATWriterFile() {
162 return tree
.config
.stateFile
;
165 long supplyATWriterFilePos() {
166 return HistoryTree
.getTreeHeaderSize()
167 + ((long) tree
.getNodeCount() * tree
.config
.blockSize
);
170 synchronized void closeFile() {
174 } catch (IOException e
) {
179 synchronized void deleteFile() {
182 if(!historyTreeFile
.delete()) {
183 /* We didn't succeed in deleting the file */
189 * Seek the given FileChannel to the position corresponding to the node that
193 * @throws IOException
195 private void seekFCToNodePos(FileChannel fc
, int seqNumber
)
197 fc
.position(HistoryTree
.getTreeHeaderSize() + (long) seqNumber
198 * tree
.config
.blockSize
);
200 * cast to (long) is needed to make sure the result is a long too and
201 * doesn't get truncated
This page took 0.036492 seconds and 6 git commands to generate.