trace/traceviewer/com.nokia.traceviewer/src/com/nokia/traceviewer/engine/dataprocessor/SearchProcessor.java
changeset 11 5b9d4d8641ce
equal deleted inserted replaced
10:ed1c9f64298a 11:5b9d4d8641ce
       
     1 /*
       
     2  * Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies). 
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of "Eclipse Public License v1.0"
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  *
       
     9  * Initial Contributors:
       
    10  * Nokia Corporation - initial contribution.
       
    11  *
       
    12  * Contributors:
       
    13  *
       
    14  * Description:
       
    15  *
       
    16  * SearchProcessor DataProcessor
       
    17  *
       
    18  */
       
    19 package com.nokia.traceviewer.engine.dataprocessor;
       
    20 
       
    21 import java.util.ArrayList;
       
    22 import java.util.List;
       
    23 
       
    24 import org.eclipse.jface.text.BadLocationException;
       
    25 import org.eclipse.jface.text.Document;
       
    26 import org.eclipse.jface.text.FindReplaceDocumentAdapter;
       
    27 import org.eclipse.jface.text.IDocument;
       
    28 import org.eclipse.jface.text.IRegion;
       
    29 import org.eclipse.ui.PlatformUI;
       
    30 
       
    31 import com.nokia.traceviewer.action.TraceViewerActionUtils;
       
    32 import com.nokia.traceviewer.dialog.SearchDialog;
       
    33 import com.nokia.traceviewer.engine.DataProcessorAccess;
       
    34 import com.nokia.traceviewer.engine.DataReader;
       
    35 import com.nokia.traceviewer.engine.DataScrollReader;
       
    36 import com.nokia.traceviewer.engine.MediaCallback;
       
    37 import com.nokia.traceviewer.engine.StateHolder;
       
    38 import com.nokia.traceviewer.engine.TraceInformation;
       
    39 import com.nokia.traceviewer.engine.TraceProperties;
       
    40 import com.nokia.traceviewer.engine.TraceViewerGlobals;
       
    41 import com.nokia.traceviewer.engine.TraceViewerDialogInterface.Dialog;
       
    42 
       
    43 /**
       
    44  * SearchProcessor DataProcessor
       
    45  */
       
    46 public final class SearchProcessor implements DataProcessor, MediaCallback {
       
    47 
       
    48 	/**
       
    49 	 * Enum indicating the error codes of TraceViewer API operations
       
    50 	 */
       
    51 	public enum TimestampSearchPhase {
       
    52 
       
    53 		/**
       
    54 		 * Timestamp search is not ongoing
       
    55 		 */
       
    56 		NONE,
       
    57 
       
    58 		/**
       
    59 		 * Finding end timestamp
       
    60 		 */
       
    61 		FINDING_END,
       
    62 
       
    63 		/**
       
    64 		 * End found
       
    65 		 */
       
    66 		END_FOUND;
       
    67 
       
    68 	}
       
    69 
       
    70 	/**
       
    71 	 * Search dialog used in searching
       
    72 	 */
       
    73 	private SearchDialog searchDialog;
       
    74 
       
    75 	/**
       
    76 	 * Temporary document used in searching
       
    77 	 */
       
    78 	private final IDocument document;
       
    79 
       
    80 	/**
       
    81 	 * Buffer to hold data before inserting all to document
       
    82 	 */
       
    83 	private final StringBuffer data;
       
    84 
       
    85 	/**
       
    86 	 * Finder adapter
       
    87 	 */
       
    88 	private final FindReplaceDocumentAdapter finder;
       
    89 
       
    90 	/**
       
    91 	 * Search properties
       
    92 	 */
       
    93 	private SearchProperties searchProperties;
       
    94 
       
    95 	/**
       
    96 	 * Timestamp range end trace number
       
    97 	 */
       
    98 	private int timestampEndTrace;
       
    99 
       
   100 	/**
       
   101 	 * Tells if we have hit EOF already
       
   102 	 */
       
   103 	private boolean hitEOFAlready;
       
   104 
       
   105 	/**
       
   106 	 * Tells that we should stop searching
       
   107 	 */
       
   108 	private boolean stopSearching;
       
   109 
       
   110 	/**
       
   111 	 * Tells that search is ongoing
       
   112 	 */
       
   113 	private boolean searchOngoing;
       
   114 
       
   115 	/**
       
   116 	 * Array containing trace informations (cid, gid and tid)
       
   117 	 */
       
   118 	private final List<TraceInformation> traceInformations;
       
   119 
       
   120 	/**
       
   121 	 * Array containing timestamp strings
       
   122 	 */
       
   123 	private final List<String> timestampStrings;
       
   124 
       
   125 	/**
       
   126 	 * Search data reader
       
   127 	 */
       
   128 	private DataScrollReader searchDataReader;
       
   129 
       
   130 	/**
       
   131 	 * Timestamp search phase
       
   132 	 */
       
   133 	private TimestampSearchPhase timestampSearchPhase = TimestampSearchPhase.NONE;
       
   134 
       
   135 	/**
       
   136 	 * Constructor
       
   137 	 */
       
   138 	public SearchProcessor() {
       
   139 		// Create needed elements and arrays
       
   140 		data = new StringBuffer();
       
   141 		document = new Document();
       
   142 		finder = new FindReplaceDocumentAdapter(document);
       
   143 		searchProperties = new SearchProperties();
       
   144 		traceInformations = new ArrayList<TraceInformation>();
       
   145 		timestampStrings = new ArrayList<String>();
       
   146 	}
       
   147 
       
   148 	/*
       
   149 	 * (non-Javadoc)
       
   150 	 * 
       
   151 	 * @see
       
   152 	 * com.nokia.traceviewer.engine.DataProcessor#processData(com.nokia.traceviewer
       
   153 	 * .engine.TraceProperties)
       
   154 	 */
       
   155 	public void processData(TraceProperties properties) {
       
   156 		DataProcessorAccess dpa = TraceViewerGlobals.getTraceViewer()
       
   157 				.getDataProcessorAccess();
       
   158 
       
   159 		// If binary trace, decode it
       
   160 		if (properties.binaryTrace) {
       
   161 			dpa.getDecoder().processData(properties);
       
   162 		}
       
   163 
       
   164 		// Parse timestamp
       
   165 		dpa.getTimestampParser().processData(properties);
       
   166 
       
   167 		// Traces missing
       
   168 		if (properties.bTraceInformation.isTraceMissing()) {
       
   169 			data.append(TraceViewerActionUtils.TRACES_DROPPED_MSG);
       
   170 		}
       
   171 
       
   172 		// Timestamp string
       
   173 		if (properties.timestampString != null) {
       
   174 			data.append(properties.timestampString);
       
   175 			data.append(dpa.getTimestampParser().getTimeFromPreviousString(
       
   176 					properties.timeFromPreviousTrace));
       
   177 			data.append('\t');
       
   178 
       
   179 			// Add to the timestampstrings array
       
   180 			timestampStrings.add(properties.timestampString);
       
   181 
       
   182 		}
       
   183 
       
   184 		// Trace string
       
   185 		data.append(properties.traceString);
       
   186 
       
   187 		// Trace comment
       
   188 		if (properties.traceComment != null) {
       
   189 			data.append(TraceViewerActionUtils.COMMENT_PREFIX);
       
   190 			data.append(properties.traceComment);
       
   191 		}
       
   192 		data.append('\n');
       
   193 
       
   194 		traceInformations.add(properties.information);
       
   195 
       
   196 		// Last trace, start search
       
   197 		if (properties.lastTrace) {
       
   198 			document.set(data.toString());
       
   199 			data.setLength(0);
       
   200 
       
   201 			// Data is received, start search
       
   202 			startSearch();
       
   203 			traceInformations.clear();
       
   204 			timestampStrings.clear();
       
   205 		}
       
   206 	}
       
   207 
       
   208 	/**
       
   209 	 * Starts search
       
   210 	 */
       
   211 	private void startSearch() {
       
   212 		if (!stopSearching) {
       
   213 			try {
       
   214 				int tracesTillNow = searchProperties
       
   215 						.getCurrentSearchStartLine()
       
   216 						+ TraceViewerGlobals.blockSize * 2;
       
   217 
       
   218 				// Get the search start offset
       
   219 				int searchStartOffset = getSearchStartOffset();
       
   220 
       
   221 				// Find the trace and get the offset of it
       
   222 				int offset = findTrace(searchStartOffset);
       
   223 
       
   224 				// Update progressBar
       
   225 				searchDialog.updateSearchProgressBar(searchProperties
       
   226 						.getCurrentSearchStartLine() + 1);
       
   227 
       
   228 				if (searchProperties.isSearchingForward()) {
       
   229 					processSearchingForward(tracesTillNow, offset);
       
   230 				} else {
       
   231 					processSearchingBackward(offset);
       
   232 				}
       
   233 
       
   234 			} catch (BadLocationException e) {
       
   235 				e.printStackTrace();
       
   236 				searchOngoing = false;
       
   237 			}
       
   238 		} else {
       
   239 			TraceViewerGlobals.getTraceViewer().getStateHolder().setState(
       
   240 					StateHolder.State.NORMAL);
       
   241 			stopSearching = false;
       
   242 			searchOngoing = false;
       
   243 		}
       
   244 
       
   245 	}
       
   246 
       
   247 	/**
       
   248 	 * Gets the correct search start offset
       
   249 	 * 
       
   250 	 * @return search start offset
       
   251 	 */
       
   252 	private int getSearchStartOffset() {
       
   253 		int searchStartOffset;
       
   254 
       
   255 		// Set proper offset to start searching from
       
   256 		if (searchProperties.isSearchingForward()) {
       
   257 			searchStartOffset = 0;
       
   258 
       
   259 			// Searching backward
       
   260 		} else {
       
   261 			searchStartOffset = document.getLength() - 1;
       
   262 		}
       
   263 
       
   264 		return searchStartOffset;
       
   265 	}
       
   266 
       
   267 	/**
       
   268 	 * Finds the trace using search properties
       
   269 	 * 
       
   270 	 * @param searchStartOffset
       
   271 	 *            start offset where to start the search
       
   272 	 * @return offset of the trace found or -1 if not found
       
   273 	 * @throws BadLocationException
       
   274 	 */
       
   275 	private int findTrace(int searchStartOffset) throws BadLocationException {
       
   276 		int offset = SearchUtils.NOT_FOUND;
       
   277 
       
   278 		// Search using component, group and trace ID's
       
   279 		if (SearchUtils.containsIdQuery(searchProperties.getSearchString())) {
       
   280 			offset = findTraceIDSearch(searchStartOffset);
       
   281 
       
   282 			// Timestamp search
       
   283 		} else if (SearchUtils.containsTimestampQuery(searchProperties
       
   284 				.getSearchString())) {
       
   285 			offset = findTraceTimestampSearch(searchStartOffset);
       
   286 
       
   287 			// Create a normal text search
       
   288 		} else {
       
   289 			timestampSearchPhase = TimestampSearchPhase.NONE;
       
   290 			IRegion region = finder.find(searchStartOffset, searchProperties
       
   291 					.getSearchString(), searchProperties.isSearchingForward(),
       
   292 					searchProperties.isCaseSensitive(), searchProperties
       
   293 							.isWholeWord(), searchProperties.isRegExp());
       
   294 
       
   295 			if (region != null) {
       
   296 				offset = region.getOffset();
       
   297 			}
       
   298 		}
       
   299 
       
   300 		return offset;
       
   301 	}
       
   302 
       
   303 	/**
       
   304 	 * Finds the trace using ID search
       
   305 	 * 
       
   306 	 * @param searchStartOffset
       
   307 	 *            search start offset
       
   308 	 * @return found offset
       
   309 	 * @throws BadLocationException
       
   310 	 */
       
   311 	private int findTraceIDSearch(int searchStartOffset)
       
   312 			throws BadLocationException {
       
   313 		int offset;
       
   314 		timestampSearchPhase = TimestampSearchPhase.NONE;
       
   315 
       
   316 		// Parse ID's from the search string
       
   317 		TraceInformation inf = SearchUtils.parseIDsFromString(searchProperties
       
   318 				.getSearchString());
       
   319 		int startTrace = document.getLineOfOffset(searchStartOffset);
       
   320 
       
   321 		// Get the trace number that matches the ID's
       
   322 		int foundTrace = SearchUtils.findTraceOffsetFromInformations(
       
   323 				startTrace, inf, traceInformations, searchProperties
       
   324 						.isSearchingForward());
       
   325 
       
   326 		if (foundTrace == SearchUtils.NOT_FOUND) {
       
   327 			offset = SearchUtils.NOT_FOUND;
       
   328 		} else {
       
   329 			offset = document.getLineOffset(foundTrace);
       
   330 		}
       
   331 		return offset;
       
   332 	}
       
   333 
       
   334 	/**
       
   335 	 * Finds the trace using timestamp search
       
   336 	 * 
       
   337 	 * @param searchStartOffset
       
   338 	 *            search start offset
       
   339 	 * @return found offset
       
   340 	 * @throws BadLocationException
       
   341 	 */
       
   342 	private int findTraceTimestampSearch(int searchStartOffset)
       
   343 			throws BadLocationException {
       
   344 		int offset;
       
   345 		boolean getFirstTimestamp = true;
       
   346 		boolean timestampSearchOnGoing = false;
       
   347 		if (timestampSearchPhase == TimestampSearchPhase.NONE
       
   348 				|| timestampSearchPhase == TimestampSearchPhase.FINDING_END) {
       
   349 			timestampSearchOnGoing = true;
       
   350 		}
       
   351 		if (SearchUtils.containsTimestampRangeQuery(searchProperties
       
   352 				.getSearchString())
       
   353 				&& timestampSearchOnGoing) {
       
   354 			getFirstTimestamp = false;
       
   355 			timestampSearchPhase = TimestampSearchPhase.FINDING_END;
       
   356 		}
       
   357 
       
   358 		// Parse timestamp from the search string
       
   359 		String timestamp = SearchUtils.parseTimestampFromString(
       
   360 				searchProperties.getSearchString(), getFirstTimestamp);
       
   361 
       
   362 		int startTrace = document.getLineOfOffset(searchStartOffset);
       
   363 
       
   364 		// Get the trace which matches the timestamp
       
   365 		int foundTrace = SearchUtils.findTraceOffsetFromTimestamps(startTrace,
       
   366 				timestamp, timestampStrings, searchProperties
       
   367 						.isSearchingForward());
       
   368 
       
   369 		if (foundTrace == SearchUtils.NOT_FOUND) {
       
   370 			offset = SearchUtils.NOT_FOUND;
       
   371 		} else {
       
   372 			offset = document.getLineOffset(foundTrace);
       
   373 		}
       
   374 		return offset;
       
   375 	}
       
   376 
       
   377 	/**
       
   378 	 * Processes situation when searching forward
       
   379 	 * 
       
   380 	 * @param tracesTillNow
       
   381 	 *            Tells how many traces is read from file
       
   382 	 * @param offset
       
   383 	 *            offset to found item
       
   384 	 * @throws BadLocationException
       
   385 	 */
       
   386 	private void processSearchingForward(int tracesTillNow, int offset)
       
   387 			throws BadLocationException {
       
   388 
       
   389 		// String found
       
   390 		if (offset != SearchUtils.NOT_FOUND) {
       
   391 			processStringFound(offset);
       
   392 
       
   393 			// Full round processed
       
   394 		} else if (tracesTillNow > searchProperties
       
   395 				.getOriginalSearchStartLine()
       
   396 				&& hitEOFAlready) {
       
   397 			fullRoundProcessed();
       
   398 			// We didn't find anything from these 2 blocks, go to next one
       
   399 		} else {
       
   400 			// Not End Of File
       
   401 			if (tracesTillNow < TraceViewerGlobals.getTraceViewer()
       
   402 					.getDataReaderAccess().getCurrentDataReader()
       
   403 					.getTraceCount()) {
       
   404 				searchProperties.setCurrentSearchStartLine(tracesTillNow + 1);
       
   405 				processSearch(searchProperties, true);
       
   406 				// End Of File
       
   407 			} else {
       
   408 				hitEOFAlready = true;
       
   409 				searchDialog.updateSearchProgressBar(TraceViewerGlobals
       
   410 						.getTraceViewer().getDataReaderAccess()
       
   411 						.getCurrentDataReader().getTraceCount());
       
   412 				searchDialog.searchHitEOF();
       
   413 				searchOngoing = false;
       
   414 			}
       
   415 		}
       
   416 	}
       
   417 
       
   418 	/**
       
   419 	 * Full round processed
       
   420 	 */
       
   421 	private void fullRoundProcessed() {
       
   422 		hitEOFAlready = false;
       
   423 		searchDialog.updateSearchProgressBar(searchProperties
       
   424 				.getOriginalSearchStartLine());
       
   425 		searchDialog.searchHitFullRound();
       
   426 		searchOngoing = false;
       
   427 	}
       
   428 
       
   429 	/**
       
   430 	 * Processes situation where result was found
       
   431 	 * 
       
   432 	 * @param offset
       
   433 	 *            offset of the result
       
   434 	 * @throws BadLocationException
       
   435 	 */
       
   436 	private void processStringFound(int offset) throws BadLocationException {
       
   437 		hitEOFAlready = false;
       
   438 		int line = document.getLineOfOffset(offset);
       
   439 
       
   440 		int foundTraceLine = searchProperties.getCurrentSearchStartLine()
       
   441 				+ line;
       
   442 
       
   443 		// Update progressBar
       
   444 		searchDialog.updateSearchProgressBar(foundTraceLine);
       
   445 
       
   446 		// Set the search line
       
   447 		if (timestampSearchPhase == TimestampSearchPhase.NONE) {
       
   448 			searchOngoing = false;
       
   449 			TraceViewerGlobals.getTraceViewer().getView().highlightLines(
       
   450 					foundTraceLine, 0, false);
       
   451 
       
   452 			// Timestamp range search
       
   453 		} else {
       
   454 			if (timestampSearchPhase == TimestampSearchPhase.FINDING_END) {
       
   455 				timestampSearchPhase = TimestampSearchPhase.END_FOUND;
       
   456 				timestampEndTrace = foundTraceLine;
       
   457 
       
   458 				// Start new search
       
   459 				searchProperties.setCurrentSearchStartLine(foundTraceLine);
       
   460 				processSearch(searchProperties, true);
       
   461 
       
   462 				// End and start both found
       
   463 			} else if (timestampSearchPhase == TimestampSearchPhase.END_FOUND) {
       
   464 				searchOngoing = false;
       
   465 				TraceViewerGlobals.getTraceViewer().getView().highlightLines(
       
   466 						foundTraceLine, timestampEndTrace, true);
       
   467 				timestampSearchPhase = TimestampSearchPhase.NONE;
       
   468 				timestampEndTrace = 0;
       
   469 			} else {
       
   470 				searchOngoing = false;
       
   471 			}
       
   472 		}
       
   473 
       
   474 	}
       
   475 
       
   476 	/**
       
   477 	 * Processes situation when searching backwards
       
   478 	 * 
       
   479 	 * @param offset
       
   480 	 *            offset to found item
       
   481 	 * @throws BadLocationException
       
   482 	 */
       
   483 	private void processSearchingBackward(int offset)
       
   484 			throws BadLocationException {
       
   485 
       
   486 		// String found
       
   487 		if (offset != SearchUtils.NOT_FOUND) {
       
   488 			processStringFound(offset);
       
   489 			// Full round processed
       
   490 		} else if (searchProperties.getCurrentSearchStartLine() <= searchProperties
       
   491 				.getOriginalSearchStartLine()
       
   492 				&& hitEOFAlready) {
       
   493 			fullRoundProcessed();
       
   494 		} else {
       
   495 			// Not End Of File
       
   496 			if (searchProperties.getCurrentSearchStartLine() > 0) {
       
   497 				searchProperties.setCurrentSearchStartLine(searchProperties
       
   498 						.getCurrentSearchStartLine()
       
   499 						- (TraceViewerGlobals.blockSize / 2));
       
   500 				processSearch(searchProperties, true);
       
   501 				// End Of File
       
   502 			} else {
       
   503 				hitEOFAlready = true;
       
   504 				searchDialog.updateSearchProgressBar(0);
       
   505 
       
   506 				// Timestamp search
       
   507 				if (timestampSearchPhase == TimestampSearchPhase.END_FOUND
       
   508 						|| timestampSearchPhase == TimestampSearchPhase.FINDING_END) {
       
   509 					if (timestampEndTrace == 0) {
       
   510 						timestampEndTrace--;
       
   511 					}
       
   512 					TraceViewerGlobals.getTraceViewer().getView()
       
   513 							.highlightLines(0, timestampEndTrace + 1, false);
       
   514 					timestampSearchPhase = TimestampSearchPhase.NONE;
       
   515 					timestampEndTrace = 0;
       
   516 
       
   517 					// Normal search
       
   518 				} else {
       
   519 					searchDialog.searchHitEOF();
       
   520 				}
       
   521 				searchOngoing = false;
       
   522 			}
       
   523 		}
       
   524 	}
       
   525 
       
   526 	/**
       
   527 	 * Sets hitEOFAlready variable
       
   528 	 * 
       
   529 	 * @param hitEOF
       
   530 	 *            boolean to set varible to
       
   531 	 */
       
   532 	public void setHitEOFAlready(boolean hitEOF) {
       
   533 		this.hitEOFAlready = hitEOF;
       
   534 	}
       
   535 
       
   536 	/**
       
   537 	 * Gets search dialog
       
   538 	 * 
       
   539 	 * @return search dialog
       
   540 	 */
       
   541 	public SearchDialog getSearchDialog() {
       
   542 		if (searchDialog == null) {
       
   543 			searchDialog = (SearchDialog) TraceViewerGlobals.getTraceViewer()
       
   544 					.getDialogs().createDialog(Dialog.SEARCH);
       
   545 		}
       
   546 		return searchDialog;
       
   547 	}
       
   548 
       
   549 	/**
       
   550 	 * Sets stop boolean as true or false. If true, searching will stop when
       
   551 	 * next block has been fetched from the file
       
   552 	 * 
       
   553 	 * @param stop
       
   554 	 *            indicates if the search should be stopped
       
   555 	 */
       
   556 	public void stopSearch(boolean stop) {
       
   557 		stopSearching = stop;
       
   558 	}
       
   559 
       
   560 	/**
       
   561 	 * Process search with given searchProperties
       
   562 	 * 
       
   563 	 * @param searchProperties
       
   564 	 *            searchproperties
       
   565 	 * @param internal
       
   566 	 *            if true, the search request is coming from TraceViewer
       
   567 	 *            internally
       
   568 	 */
       
   569 	public void processSearch(SearchProperties searchProperties,
       
   570 			boolean internal) {
       
   571 
       
   572 		// If search is already ongoing, stop it
       
   573 		if (!internal && searchOngoing) {
       
   574 			stopSearch(true);
       
   575 			while (searchOngoing) {
       
   576 				try {
       
   577 					Thread.sleep(50);
       
   578 				} catch (InterruptedException e) {
       
   579 					e.printStackTrace();
       
   580 				}
       
   581 			}
       
   582 		}
       
   583 		searchOngoing = true;
       
   584 
       
   585 		int traceCount = TraceViewerGlobals.getTraceViewer()
       
   586 				.getDataReaderAccess().getCurrentDataReader().getTraceCount();
       
   587 
       
   588 		int numberOfBlocks = 2;
       
   589 		int traceToStartReading = searchProperties.getCurrentSearchStartLine();
       
   590 
       
   591 		// Searching forward
       
   592 		if (searchProperties.isSearchingForward()) {
       
   593 
       
   594 			// Check now many blocks are needed
       
   595 			if (traceToStartReading + TraceViewerGlobals.blockSize > traceCount) {
       
   596 				numberOfBlocks = 1;
       
   597 			}
       
   598 
       
   599 			// Searching backward
       
   600 		} else {
       
   601 			// Check now many blocks are needed
       
   602 			if (traceToStartReading < TraceViewerGlobals.blockSize) {
       
   603 				numberOfBlocks = 1;
       
   604 			} else {
       
   605 				// If searching backwards, read traces from one block before
       
   606 				traceToStartReading = traceToStartReading
       
   607 						- TraceViewerGlobals.blockSize;
       
   608 			}
       
   609 		}
       
   610 
       
   611 		// Get the file position having given offset
       
   612 		int index = TraceViewerGlobals.getTraceViewer().getDataReaderAccess()
       
   613 				.getCurrentDataReader().getFileMap().getIndexFromOffset(
       
   614 						traceToStartReading);
       
   615 
       
   616 		this.searchProperties = searchProperties;
       
   617 
       
   618 		long pos = TraceViewerGlobals.getTraceViewer().getDataReaderAccess()
       
   619 				.getCurrentDataReader().getFileMap().getItem(index).longValue();
       
   620 		int startTrace = index * TraceViewerGlobals.blockSize;
       
   621 
       
   622 		this.searchProperties.setCurrentSearchStartLine(startTrace);
       
   623 
       
   624 		// Create searchDataReader if it doesn't exist and start it
       
   625 		searchDataReader = TraceViewerGlobals.getTraceViewer()
       
   626 				.getDataReaderAccess().startOwnDataReader(searchDataReader,
       
   627 						this, numberOfBlocks, pos, startTrace, false);
       
   628 	}
       
   629 
       
   630 	/**
       
   631 	 * Performs timestamp range search. Must be called from UI thread!
       
   632 	 * 
       
   633 	 * @param findStr
       
   634 	 *            find str
       
   635 	 */
       
   636 	public void doTimestampRangeSearch(String findStr) {
       
   637 		int traceCount = TraceViewerGlobals.getTraceViewer()
       
   638 				.getDataReaderAccess().getCurrentDataReader().getTraceCount();
       
   639 		searchProperties.setCurrentSearchStartLine(traceCount);
       
   640 		searchProperties.setOriginalSearchStartLine(traceCount);
       
   641 		searchProperties.setSearchString(findStr);
       
   642 		searchProperties.setSearchingForward(false);
       
   643 		getSearchDialog().setSearchText(findStr);
       
   644 		processSearch(searchProperties, false);
       
   645 	}
       
   646 
       
   647 	/*
       
   648 	 * (non-Javadoc)
       
   649 	 * 
       
   650 	 * @see
       
   651 	 * com.nokia.traceviewer.engine.MediaCallback#endOfFile(com.nokia.traceviewer
       
   652 	 * .engine.DataReader)
       
   653 	 */
       
   654 	public void endOfFile(DataReader reader) {
       
   655 		// Do nothing
       
   656 	}
       
   657 
       
   658 	/*
       
   659 	 * (non-Javadoc)
       
   660 	 * 
       
   661 	 * @see com.nokia.traceviewer.engine.MediaCallback#dataHandleChanged()
       
   662 	 */
       
   663 	public void dataHandleChanged() {
       
   664 		shutdownSearchReader();
       
   665 	}
       
   666 
       
   667 	/*
       
   668 	 * (non-Javadoc)
       
   669 	 * 
       
   670 	 * @see
       
   671 	 * com.nokia.traceviewer.engine.MediaCallback#processTrace(com.nokia.traceviewer
       
   672 	 * .engine.TraceProperties)
       
   673 	 */
       
   674 	public void processTrace(TraceProperties properties) {
       
   675 		processData(properties);
       
   676 	}
       
   677 
       
   678 	/**
       
   679 	 * Disposes search dialog. Also kill the search data reader.
       
   680 	 * 
       
   681 	 * @return true if search dialog was closed. False if it wasn't open.
       
   682 	 */
       
   683 	public boolean disposeSearchDialog() {
       
   684 		boolean closed = false;
       
   685 		if (searchDialog != null) {
       
   686 			closed = searchDialog.forceClose();
       
   687 			searchDialog = null;
       
   688 			shutdownSearchReader();
       
   689 		}
       
   690 		return closed;
       
   691 	}
       
   692 
       
   693 	/**
       
   694 	 * Shuts down search data reader
       
   695 	 */
       
   696 	public void shutdownSearchReader() {
       
   697 		if (searchDataReader != null) {
       
   698 			searchDataReader.shutdown();
       
   699 			searchDataReader = null;
       
   700 		}
       
   701 	}
       
   702 
       
   703 	/**
       
   704 	 * Searches the next trace with ID. Must be called from UI thread!
       
   705 	 * 
       
   706 	 * @param cid
       
   707 	 *            Component ID
       
   708 	 * @param gid
       
   709 	 *            Group ID
       
   710 	 * @param tid
       
   711 	 *            Trace ID
       
   712 	 */
       
   713 	public void searchTraceWithID(int cid, int gid, int tid) {
       
   714 
       
   715 		// Create search string
       
   716 		final String findStr = SearchUtils.createStringFromIDs(cid, gid, tid);
       
   717 		searchTraceWithString(findStr);
       
   718 	}
       
   719 
       
   720 	/**
       
   721 	 * Searches trace with timestamp. Must be called from UI thread and
       
   722 	 * TraceViewer view must exists!
       
   723 	 * 
       
   724 	 * @param startTimestamp
       
   725 	 *            start timestamp string
       
   726 	 * @param endTimestamp
       
   727 	 *            end timestamp string
       
   728 	 */
       
   729 	public void searchTraceWithTimestamp(final String startTimestamp,
       
   730 			final String endTimestamp) {
       
   731 
       
   732 		// Create search string
       
   733 		final String findStr = SearchUtils.createStringFromTimestamp(
       
   734 				startTimestamp, endTimestamp);
       
   735 		searchTraceWithString(findStr);
       
   736 	}
       
   737 
       
   738 	/**
       
   739 	 * Searches the next trace with text. Must be called from UI thread!
       
   740 	 * 
       
   741 	 * @param text
       
   742 	 *            text to search for
       
   743 	 */
       
   744 	public void searchTraceWithString(final String text) {
       
   745 		final SearchDialog dialog = getSearchDialog();
       
   746 		if (!dialog.isOpen()) {
       
   747 			dialog.create();
       
   748 		}
       
   749 
       
   750 		// Create a thread that will start the search because this thread will
       
   751 		// stop to message event loop when opening the search dialog
       
   752 		Thread a = new Thread() {
       
   753 
       
   754 			/*
       
   755 			 * (non-Javadoc)
       
   756 			 * 
       
   757 			 * @see java.lang.Thread#run()
       
   758 			 */
       
   759 			@Override
       
   760 			public void run() {
       
   761 				// Stop previous search
       
   762 				if (searchOngoing) {
       
   763 					stopSearch(true);
       
   764 				}
       
   765 
       
   766 				// Must be synced with the UI thread to be able to update the
       
   767 				// search dialog
       
   768 				PlatformUI.getWorkbench().getDisplay().asyncExec(
       
   769 						new Runnable() {
       
   770 
       
   771 							/*
       
   772 							 * (non-Javadoc)
       
   773 							 * 
       
   774 							 * @see java.lang.Runnable#run()
       
   775 							 */
       
   776 							public void run() {
       
   777 								dialog.startSearch(text);
       
   778 							}
       
   779 						});
       
   780 
       
   781 			}
       
   782 		};
       
   783 		a.start();
       
   784 
       
   785 		if (!dialog.isVisible()) {
       
   786 			dialog.openDialog();
       
   787 		}
       
   788 	}
       
   789 }