Merge Generic State System core part
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / statesystem / backend / historytree / HT_IO.java
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>
5 *
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
10 *
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.tmf.core.statesystem.backend.historytree;
14
15 import java.io.File;
16 import java.io.FileInputStream;
17 import java.io.FileOutputStream;
18 import java.io.IOException;
19 import java.nio.channels.FileChannel;
20
21 /**
22 * This class exists mainly for code isolation/clarification purposes. It
23 * contains all the methods and descriptors to handle reading/writing to the
24 * tree-file on disk and all the caching mechanisms. Every HistoryTree should
25 * contain 1 and only 1 HT_IO element.
26 *
27 * @author alexmont
28 *
29 */
30 class HT_IO {
31
32 /* reference to the tree to which this IO-object belongs */
33 private final HistoryTree tree;
34
35 /* Fields related to the file I/O */
36 private FileInputStream fis;
37 private FileOutputStream fos;
38 private FileChannel fcIn;
39 private FileChannel fcOut;
40
41 /**
42 * Standard constructor
43 *
44 * @param tree
45 * @param newFile Are we creating a new file from scratch?
46 * @throws IOException
47 */
48 HT_IO(HistoryTree tree, boolean newFile) throws IOException {
49 this.tree = tree;
50 File historyTreeFile = tree.config.stateFile;
51
52 if (newFile) {
53 /* Create a new empty History Tree file */
54 if (historyTreeFile.exists()) {
55 historyTreeFile.delete();
56 }
57 historyTreeFile.createNewFile();
58 fis = new FileInputStream(historyTreeFile);
59 fos = new FileOutputStream(historyTreeFile, false);
60 } else {
61 /*
62 * We want to open an existing file, make sure we don't squash the
63 * existing content when opening the fos!
64 */
65 this.fis = new FileInputStream(historyTreeFile);
66 this.fos = new FileOutputStream(historyTreeFile, true);
67 }
68 this.fcIn = fis.getChannel();
69 this.fcOut = fos.getChannel();
70 }
71
72 /**
73 * Generic "read node" method, which checks if the node is in memory first,
74 * and if it's not it goes to disk to retrieve it.
75 *
76 * @param seqNumber
77 * Sequence number of the node we want
78 * @return The wanted node in object form
79 */
80 HTNode readNode(int seqNumber) {
81 HTNode node = readNodeFromMemory(seqNumber);
82 if (node == null) {
83 return readNodeFromDisk(seqNumber);
84 }
85 return node;
86 }
87
88 private HTNode readNodeFromMemory(int seqNumber) {
89 for (HTNode node : tree.latestBranch) {
90 if (node.getSequenceNumber() == seqNumber) {
91 return node;
92 }
93 }
94 return null;
95 }
96
97 /**
98 * This method here isn't private, if we know for sure the node cannot be in
99 * memory it's a bit faster to use this directly (when opening a file from
100 * disk for example)
101 */
102 HTNode readNodeFromDisk(int seqNumber) {
103 HTNode readNode;
104 try {
105 seekFCToNodePos(fcIn, seqNumber);
106 readNode = HTNode.readNode(tree, fcIn);
107 return readNode;
108 } catch (IOException e) {
109 e.printStackTrace();
110 return null;
111 }
112 }
113
114 void writeNode(HTNode node) {
115 try {
116 /* Position ourselves at the start of the node and write it */
117 seekFCToNodePos(fcOut, node.getSequenceNumber());
118 node.writeSelf(fcOut);
119 } catch (IOException e) {
120 /* If we were able to open the file, we should be fine now... */
121 e.printStackTrace();
122 }
123 }
124
125 FileChannel getFcOut() {
126 return this.fcOut;
127 }
128
129 FileInputStream supplyATReader() {
130 try {
131 /*
132 * Position ourselves at the start of the Mapping section in the
133 * file (which is right after the Blocks)
134 */
135 seekFCToNodePos(fcIn, tree.getNodeCount());
136 } catch (IOException e) {
137 e.printStackTrace();
138 }
139 return fis;
140 }
141
142 File supplyATWriterFile() {
143 return tree.config.stateFile;
144 }
145
146 long supplyATWriterFilePos() {
147 return HistoryTree.getTreeHeaderSize()
148 + ((long) tree.getNodeCount() * tree.config.blockSize);
149 }
150
151 /**
152 * Seek the given FileChannel to the position corresponding to the node that
153 * has seqNumber
154 *
155 * @param seqNumber
156 * @throws IOException
157 */
158 private void seekFCToNodePos(FileChannel fc, int seqNumber)
159 throws IOException {
160 fc.position(HistoryTree.getTreeHeaderSize() + (long) seqNumber
161 * tree.config.blockSize);
162 /*
163 * cast to (long) is needed to make sure the result is a long too and
164 * doesn't get truncated
165 */
166 }
167
168 }
This page took 0.040028 seconds and 5 git commands to generate.