ctf: Plug the unsigned utils comparator into Stream comparator.
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / internal / tmf / core / statesystem / backends / historytree / HistoryTree.java
CommitLineData
a52fde77 1/*******************************************************************************
61759503 2 * Copyright (c) 2012, 2013 Ericsson
a52fde77
AM
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
3b7f5abe 5 *
a52fde77
AM
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
3b7f5abe 10 *
a52fde77
AM
11 *******************************************************************************/
12
f9a76cac 13package org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.historytree;
a52fde77
AM
14
15import java.io.File;
16import java.io.FileInputStream;
17import java.io.IOException;
18import java.io.PrintWriter;
19import java.nio.ByteBuffer;
20import java.nio.ByteOrder;
3b7f5abe 21import java.nio.channels.ClosedChannelException;
a52fde77 22import java.nio.channels.FileChannel;
cb42195c
AM
23import java.util.ArrayList;
24import java.util.Collections;
25import java.util.List;
a52fde77 26
6d08acca 27import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
0fe46f2a 28import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateProvider;
a52fde77
AM
29
30/**
31 * Meta-container for the History Tree. This structure contains all the
32 * high-level data relevant to the tree.
3b7f5abe 33 *
a52fde77 34 * @author alexmont
3b7f5abe 35 *
a52fde77
AM
36 */
37class HistoryTree {
38
cb42195c
AM
39 /**
40 * Size of the "tree header" in the tree-file The nodes will use this offset
41 * to know where they should be in the file. This should always be a
42 * multiple of 4K.
43 */
44 public static final int TREE_HEADER_SIZE = 4096;
45
a52fde77
AM
46 private static final int HISTORY_FILE_MAGIC_NUMBER = 0x05FFA900;
47
a96cc6be
AM
48 /** File format version. Increment when breaking compatibility. */
49 private static final int FILE_VERSION = 3;
a52fde77 50
dbdc452f
AM
51 // ------------------------------------------------------------------------
52 // Tree-specific configuration
53 // ------------------------------------------------------------------------
54
55 /** Container for all the configuration constants */
cb42195c 56 private final HTConfig config;
a52fde77 57
dbdc452f 58 /** Reader/writer object */
a52fde77
AM
59 private final HT_IO treeIO;
60
dbdc452f
AM
61 // ------------------------------------------------------------------------
62 // Variable Fields (will change throughout the existance of the SHT)
63 // ------------------------------------------------------------------------
64
65 /** Latest timestamp found in the tree (at any given moment) */
a52fde77
AM
66 private long treeEnd;
67
dbdc452f 68 /** How many nodes exist in this tree, total */
a52fde77
AM
69 private int nodeCount;
70
dbdc452f 71 /** "Cache" to keep the active nodes in memory */
cb42195c 72 private List<CoreNode> latestBranch;
a52fde77 73
dbdc452f
AM
74 // ------------------------------------------------------------------------
75 // Constructors/"Destructors"
76 // ------------------------------------------------------------------------
77
a52fde77
AM
78 /**
79 * Create a new State History from scratch, using a SHTConfig object for
80 * configuration
a52fde77 81 */
7453b40e 82 HistoryTree(HTConfig conf) throws IOException {
a52fde77 83 /*
dbdc452f 84 * Simple check to make sure we have enough place in the 0th block
a52fde77
AM
85 * for the tree configuration
86 */
cb42195c 87 if (conf.getBlockSize() < TREE_HEADER_SIZE) {
dbdc452f
AM
88 throw new IllegalArgumentException();
89 }
a52fde77
AM
90
91 config = conf;
cb42195c 92 treeEnd = conf.getTreeStart();
a52fde77 93 nodeCount = 0;
cb42195c 94 latestBranch = new ArrayList<CoreNode>();
a52fde77
AM
95
96 /* Prepare the IO object */
97 treeIO = new HT_IO(this, true);
98
99 /* Add the first node to the tree */
cb42195c 100 CoreNode firstNode = initNewCoreNode(-1, conf.getTreeStart());
a52fde77
AM
101 latestBranch.add(firstNode);
102 }
103
a52fde77
AM
104 /**
105 * "Reader" constructor : instantiate a SHTree from an existing tree file on
106 * disk
3b7f5abe 107 *
a52fde77
AM
108 * @param existingFileName
109 * Path/filename of the history-file we are to open
a96cc6be
AM
110 * @param expProviderVersion
111 * The expected version of the state provider
a52fde77
AM
112 * @throws IOException
113 */
a96cc6be 114 HistoryTree(File existingStateFile, int expProviderVersion) throws IOException {
a52fde77
AM
115 /*
116 * Open the file ourselves, get the tree header information we need,
117 * then pass on the descriptor to the TreeIO object.
118 */
119 int rootNodeSeqNb, res;
120 int bs, maxc;
fb12b0c2 121 long startTime;
a52fde77
AM
122
123 /* Java I/O mumbo jumbo... */
fee997a5
AM
124 if (!existingStateFile.exists()) {
125 throw new IOException("Selected state file does not exist"); //$NON-NLS-1$
126 }
fb12b0c2 127 if (existingStateFile.length() <= 0) {
a96cc6be 128 throw new IOException("Empty target file"); //$NON-NLS-1$
a52fde77
AM
129 }
130
131 FileInputStream fis = new FileInputStream(existingStateFile);
cb42195c 132 ByteBuffer buffer = ByteBuffer.allocate(TREE_HEADER_SIZE);
a52fde77
AM
133 FileChannel fc = fis.getChannel();
134 buffer.order(ByteOrder.LITTLE_ENDIAN);
135 buffer.clear();
136 fc.read(buffer);
137 buffer.flip();
138
139 /*
140 * Check the magic number,to make sure we're opening the right type of
141 * file
142 */
143 res = buffer.getInt();
144 if (res != HISTORY_FILE_MAGIC_NUMBER) {
6f04204e
AM
145 fc.close();
146 fis.close();
a96cc6be 147 throw new IOException("Wrong magic number"); //$NON-NLS-1$
a52fde77
AM
148 }
149
a96cc6be
AM
150 res = buffer.getInt(); /* File format version number */
151 if (res != FILE_VERSION) {
6f04204e
AM
152 fc.close();
153 fis.close();
a96cc6be 154 throw new IOException("Mismatching History Tree file format versions"); //$NON-NLS-1$
a52fde77
AM
155 }
156
a96cc6be
AM
157 res = buffer.getInt(); /* Event handler's version number */
158 if (res != expProviderVersion &&
0fe46f2a 159 expProviderVersion != ITmfStateProvider.IGNORE_PROVIDER_VERSION) {
a96cc6be
AM
160 /*
161 * The existing history was built using a event handler that doesn't
162 * match the current one in the framework. Information could be all
163 * wrong, so we'll force a rebuild of the history file instead.
164 */
165 fc.close();
166 fis.close();
167 throw new IOException("Mismatching event handler versions"); //$NON-NLS-1$
168 }
a52fde77
AM
169
170 bs = buffer.getInt(); /* Block Size */
171 maxc = buffer.getInt(); /* Max nb of children per node */
172
173 this.nodeCount = buffer.getInt();
174 rootNodeSeqNb = buffer.getInt();
fb12b0c2 175 startTime = buffer.getLong();
a52fde77 176
a96cc6be 177 this.config = new HTConfig(existingStateFile, bs, maxc, expProviderVersion, startTime);
6f04204e 178 fc.close();
a52fde77
AM
179 fis.close();
180 /*
181 * FIXME We close fis here and the TreeIO will then reopen the same
182 * file, not extremely elegant. But how to pass the information here to
183 * the SHT otherwise?
184 */
185 this.treeIO = new HT_IO(this, false);
186
187 rebuildLatestBranch(rootNodeSeqNb);
cb42195c 188 this.treeEnd = latestBranch.get(0).getNodeEnd();
fb12b0c2
AM
189
190 /*
191 * Make sure the history start time we read previously is consistent
192 * with was is actually in the root node.
193 */
cb42195c 194 if (startTime != latestBranch.get(0).getNodeStart()) {
fb12b0c2
AM
195 fc.close();
196 fis.close();
197 throw new IOException("Inconsistent start times in the" + //$NON-NLS-1$
198 "history file, it might be corrupted."); //$NON-NLS-1$
199 }
a52fde77
AM
200 }
201
202 /**
203 * "Save" the tree to disk. This method will cause the treeIO object to
204 * commit all nodes to disk and then return the RandomAccessFile descriptor
205 * so the Tree object can save its configuration into the header of the
206 * file.
3b7f5abe 207 *
a52fde77
AM
208 * @param requestedEndTime
209 */
6a1074ce 210 void closeTree(long requestedEndTime) {
a52fde77
AM
211 FileChannel fc;
212 ByteBuffer buffer;
213 int i, res;
214
3b7f5abe 215 /*
6a1074ce
AM
216 * Work-around the "empty branches" that get created when the root node
217 * becomes full. Overwrite the tree's end time with the original wanted
218 * end-time, to ensure no queries are sent into those empty nodes.
3b7f5abe 219 *
6a1074ce
AM
220 * This won't be needed once extended nodes are implemented.
221 */
222 this.treeEnd = requestedEndTime;
223
a52fde77
AM
224 /* Close off the latest branch of the tree */
225 for (i = 0; i < latestBranch.size(); i++) {
226 latestBranch.get(i).closeThisNode(treeEnd);
227 treeIO.writeNode(latestBranch.get(i));
228 }
229
a52fde77 230 fc = treeIO.getFcOut();
cb42195c 231 buffer = ByteBuffer.allocate(TREE_HEADER_SIZE);
a52fde77
AM
232 buffer.order(ByteOrder.LITTLE_ENDIAN);
233 buffer.clear();
234
235 /* Save the config of the tree to the header of the file */
236 try {
237 fc.position(0);
238
239 buffer.putInt(HISTORY_FILE_MAGIC_NUMBER);
240
a96cc6be 241 buffer.putInt(FILE_VERSION);
cb42195c 242 buffer.putInt(config.getProviderVersion());
a52fde77 243
cb42195c
AM
244 buffer.putInt(config.getBlockSize());
245 buffer.putInt(config.getMaxChildren());
a52fde77
AM
246
247 buffer.putInt(nodeCount);
248
249 /* root node seq. nb */
cb42195c 250 buffer.putInt(latestBranch.get(0).getSequenceNumber());
a52fde77 251
fb12b0c2 252 /* start time of this history */
cb42195c 253 buffer.putLong(latestBranch.get(0).getNodeStart());
fb12b0c2 254
a52fde77
AM
255 buffer.flip();
256 res = fc.write(buffer);
cb42195c 257 assert (res <= TREE_HEADER_SIZE);
a52fde77
AM
258 /* done writing the file header */
259
260 } catch (IOException e) {
6f04204e 261 /* We should not have any problems at this point... */
6f04204e
AM
262 } finally {
263 try {
264 fc.close();
265 } catch (IOException e) {
6f04204e 266 }
a52fde77
AM
267 }
268 return;
269 }
270
dbdc452f
AM
271 // ------------------------------------------------------------------------
272 // Accessors
273 // ------------------------------------------------------------------------
ab604305 274
cb42195c
AM
275 HTConfig getConfig() {
276 return config;
277 }
278
a52fde77 279 long getTreeStart() {
cb42195c 280 return config.getTreeStart();
a52fde77
AM
281 }
282
283 long getTreeEnd() {
284 return treeEnd;
285 }
286
287 int getNodeCount() {
288 return nodeCount;
289 }
290
291 HT_IO getTreeIO() {
292 return treeIO;
293 }
294
cb42195c
AM
295 List<CoreNode> getLatestBranch() {
296 return Collections.unmodifiableList(latestBranch);
297 }
298
dbdc452f
AM
299 // ------------------------------------------------------------------------
300 // Operations
301 // ------------------------------------------------------------------------
302
a52fde77
AM
303 /**
304 * Rebuild the latestBranch "cache" object by reading the nodes from disk
305 * (When we are opening an existing file on disk and want to append to it,
306 * for example).
3b7f5abe 307 *
a52fde77
AM
308 * @param rootNodeSeqNb
309 * The sequence number of the root node, so we know where to
310 * start
3b7f5abe 311 * @throws ClosedChannelException
a52fde77 312 */
3b7f5abe 313 private void rebuildLatestBranch(int rootNodeSeqNb) throws ClosedChannelException {
a52fde77
AM
314 HTNode nextChildNode;
315
cb42195c 316 this.latestBranch = new ArrayList<CoreNode>();
a52fde77
AM
317
318 nextChildNode = treeIO.readNodeFromDisk(rootNodeSeqNb);
319 latestBranch.add((CoreNode) nextChildNode);
cb42195c
AM
320 while (latestBranch.get(latestBranch.size() - 1).getNbChildren() > 0) {
321 nextChildNode = treeIO.readNodeFromDisk(latestBranch.get(latestBranch.size() - 1).getLatestChild());
a52fde77
AM
322 latestBranch.add((CoreNode) nextChildNode);
323 }
324 }
325
326 /**
327 * Insert an interval in the tree
3b7f5abe 328 *
a52fde77
AM
329 * @param interval
330 */
331 void insertInterval(HTInterval interval) throws TimeRangeException {
cb42195c 332 if (interval.getStartTime() < config.getTreeStart()) {
a52fde77
AM
333 throw new TimeRangeException();
334 }
335 tryInsertAtNode(interval, latestBranch.size() - 1);
336 }
337
338 /**
339 * Inner method to find in which node we should add the interval.
3b7f5abe 340 *
a52fde77
AM
341 * @param interval
342 * The interval to add to the tree
343 * @param indexOfNode
344 * The index *in the latestBranch* where we are trying the
345 * insertion
346 */
347 private void tryInsertAtNode(HTInterval interval, int indexOfNode) {
348 HTNode targetNode = latestBranch.get(indexOfNode);
349
350 /* Verify if there is enough room in this node to store this interval */
351 if (interval.getIntervalSize() > targetNode.getNodeFreeSpace()) {
352 /* Nope, not enough room. Insert in a new sibling instead. */
353 addSiblingNode(indexOfNode);
354 tryInsertAtNode(interval, latestBranch.size() - 1);
355 return;
356 }
357
358 /* Make sure the interval time range fits this node */
359 if (interval.getStartTime() < targetNode.getNodeStart()) {
360 /*
361 * No, this interval starts before the startTime of this node. We
362 * need to check recursively in parents if it can fit.
363 */
364 assert (indexOfNode >= 1);
365 tryInsertAtNode(interval, indexOfNode - 1);
366 return;
367 }
368
369 /*
370 * Ok, there is room, and the interval fits in this time slot. Let's add
371 * it.
372 */
373 targetNode.addInterval(interval);
374
375 /* Update treeEnd if needed */
376 if (interval.getEndTime() > this.treeEnd) {
377 this.treeEnd = interval.getEndTime();
378 }
379 return;
380 }
381
382 /**
383 * Method to add a sibling to any node in the latest branch. This will add
384 * children back down to the leaf level, if needed.
3b7f5abe 385 *
a52fde77
AM
386 * @param indexOfNode
387 * The index in latestBranch where we start adding
388 */
389 private void addSiblingNode(int indexOfNode) {
390 int i;
391 CoreNode newNode, prevNode;
392 long splitTime = treeEnd;
393
394 assert (indexOfNode < latestBranch.size());
395
396 /* Check if we need to add a new root node */
397 if (indexOfNode == 0) {
398 addNewRootNode();
399 return;
400 }
401
402 /* Check if we can indeed add a child to the target parent */
cb42195c 403 if (latestBranch.get(indexOfNode - 1).getNbChildren() == config.getMaxChildren()) {
a52fde77
AM
404 /* If not, add a branch starting one level higher instead */
405 addSiblingNode(indexOfNode - 1);
406 return;
407 }
408
409 /* Split off the new branch from the old one */
410 for (i = indexOfNode; i < latestBranch.size(); i++) {
411 latestBranch.get(i).closeThisNode(splitTime);
412 treeIO.writeNode(latestBranch.get(i));
413
414 prevNode = latestBranch.get(i - 1);
415 newNode = initNewCoreNode(prevNode.getSequenceNumber(),
416 splitTime + 1);
417 prevNode.linkNewChild(newNode);
418
419 latestBranch.set(i, newNode);
420 }
421 return;
422 }
423
424 /**
425 * Similar to the previous method, except here we rebuild a completely new
426 * latestBranch
427 */
428 private void addNewRootNode() {
429 int i, depth;
430 CoreNode oldRootNode, newRootNode, newNode, prevNode;
431 long splitTime = this.treeEnd;
432
cb42195c
AM
433 oldRootNode = latestBranch.get(0);
434 newRootNode = initNewCoreNode(-1, config.getTreeStart());
a52fde77
AM
435
436 /* Tell the old root node that it isn't root anymore */
437 oldRootNode.setParentSequenceNumber(newRootNode.getSequenceNumber());
438
439 /* Close off the whole current latestBranch */
440 for (i = 0; i < latestBranch.size(); i++) {
441 latestBranch.get(i).closeThisNode(splitTime);
442 treeIO.writeNode(latestBranch.get(i));
443 }
444
445 /* Link the new root to its first child (the previous root node) */
446 newRootNode.linkNewChild(oldRootNode);
447
448 /* Rebuild a new latestBranch */
449 depth = latestBranch.size();
cb42195c 450 latestBranch = new ArrayList<CoreNode>();
a52fde77
AM
451 latestBranch.add(newRootNode);
452 for (i = 1; i < depth + 1; i++) {
453 prevNode = latestBranch.get(i - 1);
454 newNode = initNewCoreNode(prevNode.getParentSequenceNumber(),
455 splitTime + 1);
456 prevNode.linkNewChild(newNode);
457 latestBranch.add(newNode);
458 }
459 }
460
461 /**
462 * Add a new empty node to the tree.
3b7f5abe 463 *
a52fde77
AM
464 * @param parentSeqNumber
465 * Sequence number of this node's parent
466 * @param startTime
467 * Start time of the new node
468 * @return The newly created node
469 */
470 private CoreNode initNewCoreNode(int parentSeqNumber, long startTime) {
471 CoreNode newNode = new CoreNode(this, this.nodeCount, parentSeqNumber,
472 startTime);
473 this.nodeCount++;
474
475 /* Update the treeEnd if needed */
476 if (startTime >= this.treeEnd) {
477 this.treeEnd = startTime + 1;
478 }
479 return newNode;
480 }
481
482 /**
483 * Inner method to select the next child of the current node intersecting
484 * the given timestamp. Useful for moving down the tree following one
485 * branch.
3b7f5abe 486 *
a52fde77
AM
487 * @param currentNode
488 * @param t
489 * @return The child node intersecting t
3b7f5abe
AM
490 * @throws ClosedChannelException
491 * If the file channel was closed while we were reading the tree
a52fde77 492 */
3b7f5abe 493 HTNode selectNextChild(CoreNode currentNode, long t) throws ClosedChannelException {
a52fde77
AM
494 assert (currentNode.getNbChildren() > 0);
495 int potentialNextSeqNb = currentNode.getSequenceNumber();
496
497 for (int i = 0; i < currentNode.getNbChildren(); i++) {
498 if (t >= currentNode.getChildStart(i)) {
499 potentialNextSeqNb = currentNode.getChild(i);
500 } else {
501 break;
502 }
503 }
504 /*
505 * Once we exit this loop, we should have found a children to follow. If
506 * we didn't, there's a problem.
507 */
508 assert (potentialNextSeqNb != currentNode.getSequenceNumber());
509
510 /*
511 * Since this code path is quite performance-critical, avoid iterating
512 * through the whole latestBranch array if we know for sure the next
513 * node has to be on disk
514 */
515 if (currentNode.isDone()) {
516 return treeIO.readNodeFromDisk(potentialNextSeqNb);
517 }
518 return treeIO.readNode(potentialNextSeqNb);
519 }
520
a52fde77 521 long getFileSize() {
cb42195c 522 return config.getStateFile().length();
a52fde77
AM
523 }
524
3b7f5abe
AM
525 // ------------------------------------------------------------------------
526 // Test/debugging methods
527 // ------------------------------------------------------------------------
a52fde77
AM
528
529 /* Only used for debugging, shouldn't be externalized */
530 @SuppressWarnings("nls")
531 boolean checkNodeIntegrity(HTNode zenode) {
ab604305 532
a52fde77
AM
533 HTNode otherNode;
534 CoreNode node;
ab604305 535 StringBuffer buf = new StringBuffer();
a52fde77
AM
536 boolean ret = true;
537
538 // FIXME /* Only testing Core Nodes for now */
539 if (!(zenode instanceof CoreNode)) {
540 return true;
541 }
542
543 node = (CoreNode) zenode;
544
3b7f5abe
AM
545 try {
546 /*
547 * Test that this node's start and end times match the start of the
548 * first child and the end of the last child, respectively
549 */
550 if (node.getNbChildren() > 0) {
551 otherNode = treeIO.readNode(node.getChild(0));
552 if (node.getNodeStart() != otherNode.getNodeStart()) {
553 buf.append("Start time of node (" + node.getNodeStart() + ") "
554 + "does not match start time of first child " + "("
555 + otherNode.getNodeStart() + "), " + "node #"
ab604305 556 + otherNode.getSequenceNumber() + ")\n");
a52fde77
AM
557 ret = false;
558 }
3b7f5abe
AM
559 if (node.isDone()) {
560 otherNode = treeIO.readNode(node.getLatestChild());
561 if (node.getNodeEnd() != otherNode.getNodeEnd()) {
562 buf.append("End time of node (" + node.getNodeEnd()
563 + ") does not match end time of last child ("
564 + otherNode.getNodeEnd() + ", node #"
565 + otherNode.getSequenceNumber() + ")\n");
566 ret = false;
567 }
568 }
a52fde77 569 }
a52fde77 570
3b7f5abe
AM
571 /*
572 * Test that the childStartTimes[] array matches the real nodes' start
573 * times
574 */
575 for (int i = 0; i < node.getNbChildren(); i++) {
576 otherNode = treeIO.readNode(node.getChild(i));
577 if (otherNode.getNodeStart() != node.getChildStart(i)) {
578 buf.append(" Expected start time of child node #"
579 + node.getChild(i) + ": " + node.getChildStart(i)
580 + "\n" + " Actual start time of node #"
581 + otherNode.getSequenceNumber() + ": "
582 + otherNode.getNodeStart() + "\n");
583 ret = false;
584 }
a52fde77 585 }
3b7f5abe
AM
586
587 } catch (ClosedChannelException e) {
588 e.printStackTrace();
a52fde77
AM
589 }
590
591 if (!ret) {
592 System.out.println("");
593 System.out.println("SHT: Integrity check failed for node #"
594 + node.getSequenceNumber() + ":");
ab604305 595 System.out.println(buf.toString());
a52fde77
AM
596 }
597 return ret;
598 }
599
600 void checkIntegrity() {
3b7f5abe
AM
601 try {
602 for (int i = 0; i < nodeCount; i++) {
603 checkNodeIntegrity(treeIO.readNode(i));
604 }
605 } catch (ClosedChannelException e) {
a52fde77
AM
606 }
607 }
608
609 /* Only used for debugging, shouldn't be externalized */
610 @SuppressWarnings("nls")
611 @Override
612 public String toString() {
613 return "Information on the current tree:\n\n" + "Blocksize: "
cb42195c
AM
614 + config.getBlockSize() + "\n" + "Max nb. of children per node: "
615 + config.getMaxChildren() + "\n" + "Number of nodes: " + nodeCount
a52fde77
AM
616 + "\n" + "Depth of the tree: " + latestBranch.size() + "\n"
617 + "Size of the treefile: " + this.getFileSize() + "\n"
618 + "Root node has sequence number: "
cb42195c 619 + latestBranch.get(0).getSequenceNumber() + "\n"
a52fde77 620 + "'Latest leaf' has sequence number: "
cb42195c 621 + latestBranch.get(latestBranch.size() - 1).getSequenceNumber();
a52fde77
AM
622 }
623
624 private int curDepth;
625
626 /**
627 * Start at currentNode and print the contents of all its children, in
628 * pre-order. Give the root node in parameter to visit the whole tree, and
629 * have a nice overview.
630 */
631 @SuppressWarnings("nls")
632 private void preOrderPrint(PrintWriter writer, boolean printIntervals,
633 CoreNode currentNode) {
634 /* Only used for debugging, shouldn't be externalized */
635 int i, j;
636 HTNode nextNode;
637
638 writer.println(currentNode.toString());
639 if (printIntervals) {
640 currentNode.debugPrintIntervals(writer);
641 }
642 curDepth++;
643
3b7f5abe
AM
644 try {
645 for (i = 0; i < currentNode.getNbChildren(); i++) {
646 nextNode = treeIO.readNode(currentNode.getChild(i));
647 assert (nextNode instanceof CoreNode); // TODO temporary
648 for (j = 0; j < curDepth - 1; j++) {
649 writer.print(" ");
650 }
651 writer.print("+-");
652 preOrderPrint(writer, printIntervals, (CoreNode) nextNode);
a52fde77 653 }
3b7f5abe
AM
654 } catch (ClosedChannelException e) {
655 e.printStackTrace();
a52fde77
AM
656 }
657 curDepth--;
658 return;
659 }
660
661 /**
662 * Print out the full tree for debugging purposes
3b7f5abe 663 *
a52fde77
AM
664 * @param writer
665 * PrintWriter in which to write the output
666 * @param printIntervals
667 * Says if you want to output the full interval information
668 */
669 void debugPrintFullTree(PrintWriter writer, boolean printIntervals) {
670 /* Only used for debugging, shouldn't be externalized */
671 curDepth = 0;
cb42195c 672 this.preOrderPrint(writer, false, latestBranch.get(0));
a52fde77
AM
673
674 if (printIntervals) {
675 writer.println("\nDetails of intervals:"); //$NON-NLS-1$
676 curDepth = 0;
cb42195c 677 this.preOrderPrint(writer, true, latestBranch.get(0));
a52fde77
AM
678 }
679 writer.println('\n');
680 }
681
682}
This page took 0.076789 seconds and 5 git commands to generate.