/// <summary> /// Gets a subset of search results to search in based on the current criteria /// </summary> /// <param name="criteriaSet"></param> /// <returns>Search subset</returns> protected virtual SearchSubset GetSearchSubset(SearchCriteriaSet criteriaSet) { ICacheable finalEntry = null; int hashSum = criteriaSet.DescriptionFilter.GetHashCode(); int i, n = criteriaSet.Count; for (i = 0; i < n; i++) { ISearchCriteria criteria = criteriaSet[i]; //combine the current hash with the pervious hash hashSum = hashSum ^ criteria.GetHashCode(); //check if a subset is cached for this hash ICacheable entry = SearchSubsetsCache.Instance.GetEntry(hashSum); if (entry != null) { criteriaSet.StartCriteriaIndex = i; finalEntry = entry; } else { break; } } SearchSubset subset = null; if (finalEntry != null) { subset = finalEntry.GetClone() as SearchSubset; } return(subset); }
/// <summary> /// Makes a clone /// </summary> /// <returns></returns> public object Clone() { SearchSubset clone = new SearchSubset(); clone.AddRange(this); return(clone); }
/// <summary> /// Performs a search /// </summary> /// <param name="dataSource">Traffic data accesssor</param> /// <param name="criteriaSet">Set of criteria for the search</param> /// <param name="result">The search result</param> public void Search(ITrafficDataAccessor dataSource, SearchCriteriaSet criteriaSet, ISearchResult result) { _stopSearch = false; //check the search results cache int hash = GetSearchHash(dataSource, criteriaSet); ICacheable entry = SearchResultCache.Instance.GetEntry(hash); ISearchResult cachedResult = null; if (entry != null) { cachedResult = entry.Reserve() as ISearchResult; entry.Release(); } if (cachedResult == null) { //check for a subset SearchSubset subset = GetSearchSubset(criteriaSet); if (subset == null) { FullSearch(dataSource, criteriaSet, result); } else { SubsetSearch(dataSource, criteriaSet, result, subset); } //cache the search SearchResultCache.Instance.Add(hash, new CacheEntry(result)); } else { result.AddRange(cachedResult); } }
/// <summary> /// Retrive any cached subsets for the criterias of this search /// </summary> /// <param name="criteriaSet"></param> /// <returns></returns> protected override SearchSubset GetSearchSubset(SearchCriteriaSet criteriaSet) { SearchSubset subset = base.GetSearchSubset(criteriaSet); //increment the start criteria index past the criteria of the subset //explanation: for searches where we don't need to extract line information or the text of the match //we don't need to re-check the criteria if (subset != null) { criteriaSet.StartCriteriaIndex++; } return(subset); }
/// <summary> /// Calculates the weight of a cache element /// </summary> /// <param name="key"></param> /// <returns></returns> protected override int CalculateWeight(int key) { try { SearchSubset set = _entries[key].Reserve() as SearchSubset; int result = _weigthsIndex[key] + set.Count + 1; _entries[key].Release(); return(result); } catch { return(Int32.MaxValue); } }
/// <summary> /// Searches only in the specified subset /// </summary> /// <param name="dataSource"></param> /// <param name="criteriaSet"></param> /// <param name="result"></param> /// <param name="subset"></param> private void SubsetSearch(ITrafficDataAccessor dataSource, SearchCriteriaSet criteriaSet, ISearchResult result, SearchSubset subset) { foreach (int reqId in subset) { TVRequestInfo header = dataSource.GetRequestInfo(reqId); if (_stopSearch) { break; } if (header != null) { RequestMatches(dataSource, header, criteriaSet, result); } } }
/// <summary> /// Verifies a request /// </summary> /// <param name="dataSource"></param> /// <param name="header"></param> /// <param name="criteriaSet"></param> /// <param name="result"></param> protected override void RequestMatches(ITrafficDataAccessor dataSource, TVRequestInfo header, SearchCriteriaSet criteriaSet, ISearchResult result) { bool found = false; int hashSum = criteriaSet.DescriptionFilter.GetHashCode(); List <MatchCoordinates> matchCoordinates; //variable used to obtain match coordinates //create a temp list to store all the matches LineMatches tempMatches = new LineMatches(); if (criteriaSet.DescriptionFilter == null || criteriaSet.DescriptionFilter == String.Empty || header.Description.IndexOf(criteriaSet.DescriptionFilter, StringComparison.CurrentCultureIgnoreCase) > -1) { //apply an AND operation with all the search criterias from the last search criteria cached int i, n = criteriaSet.Count, start = criteriaSet.StartCriteriaIndex; for (i = start; i < n; i++) { ISearchCriteria criteria = criteriaSet[i]; found = false; //compose the text to search if (criteria.Context == SearchContext.RequestLine) { if (criteria.Matches(header.RequestLine, 0, out matchCoordinates)) { //if we got here it means that the request line matches //using the request search context since we really care only for request or response found = true; tempMatches.Add(new LineMatch(header.Id, header.RequestLine, matchCoordinates, SearchContext.Request)); } else { found = false; break; //one of the criteria did not match so the end result is false } } else { //search in request first if (criteria.Context == SearchContext.Full || criteria.Context == SearchContext.Request || criteria.Context == SearchContext.RequestBody) { found = SearchInContext(dataSource, header, criteria, SearchContext.Request, ref tempMatches); } if (criteria.Context == SearchContext.Full || criteria.Context == SearchContext.Response) { found |= SearchInContext(dataSource, header, criteria, SearchContext.Response, ref tempMatches); } if (!found) { break; //no match was found in the entire stream } } //if at the end of criteria iteration found is still true cache the hashSum of this criteria //so we can get the sublist of request ids in future searches if (found) { hashSum = hashSum ^ criteria.GetHashCode(); SearchSubset subset = null; ICacheable entry = SearchSubsetsCache.Instance.GetEntry(hashSum); if (entry == null) { subset = new SearchSubset(); subset.Add(header.Id); SearchSubsetsCache.Instance.Add(hashSum, new CacheEntry(subset)); } else { subset = entry.Reserve() as SearchSubset; if (!subset.Contains(header.Id)) { subset.Add(header.Id); } entry.Release(); } } } //end of for, all the criterias were matched or one criteria did not match if (found) { //add all the temp matches to the results result.AddRange(tempMatches); } } }
/// <summary> /// Verifies that a request matches /// </summary> /// <param name="dataSource"></param> /// <param name="header"></param> /// <param name="criteriaSet"></param> /// <param name="result"></param> protected override void RequestMatches(ITrafficDataAccessor dataSource, TVRequestInfo header, SearchCriteriaSet criteriaSet, ISearchResult result) { bool found = true; int hashSum = criteriaSet.DescriptionFilter.GetHashCode(); if (criteriaSet.DescriptionFilter == null || criteriaSet.DescriptionFilter == String.Empty || header.Description.IndexOf(criteriaSet.DescriptionFilter, StringComparison.CurrentCultureIgnoreCase) > -1) { //apply an AND operation with all the search criterias from the last search criteria cached int i, n = criteriaSet.Count, start = criteriaSet.StartCriteriaIndex; for (i = start; i < n; i++) { ISearchCriteria criteria = criteriaSet[i]; //compose the text to search string toBeSearched; if (criteria.Context == SearchContext.RequestLine) { toBeSearched = header.RequestLine; } else if (criteria.Context == SearchContext.RequestBody || criteria.Context == SearchContext.Request) { toBeSearched = Constants.DefaultEncoding.GetString(dataSource.LoadRequestData(header.Id)); if (criteria.Context == SearchContext.RequestBody) { HttpRequestInfo reqInfo = new HttpRequestInfo(toBeSearched); toBeSearched = reqInfo.ContentDataString; } } else if (criteria.Context == SearchContext.Response) { toBeSearched = Constants.DefaultEncoding.GetString(dataSource.LoadResponseData(header.Id)); } else { string request = Constants.DefaultEncoding.GetString(dataSource.LoadRequestData(header.Id)); string response = Constants.DefaultEncoding.GetString(dataSource.LoadResponseData(header.Id)); StringBuilder sb = new StringBuilder(request.Length + response.Length); sb.Append(request); sb.Append(response); toBeSearched = sb.ToString(); } found = criteria.Matches(toBeSearched); if (found) //if found is still true cache the request id as a match for the current set of criterias { hashSum = hashSum ^ criteria.GetHashCode(); ICacheable entry = SearchSubsetsCache.Instance.GetEntry(hashSum); SearchSubset subset; if (entry == null) { subset = new SearchSubset(); subset.Add(header.Id); SearchSubsetsCache.Instance.Add(hashSum, new CacheEntry(subset)); } else { subset = entry.Reserve() as SearchSubset; //if (!subset.Contains(header.Id)) //not checking if the entry exists for performance reasons //{ subset.Add(header.Id); //} entry.Release(); } } else { break; //criteria didn't match, break the loop } } //end of for, all the criterias were matched or one criteria did not match if (found) { //add all the temp matches to the results result.Add(header.Id); } } //end description check }