/// <summary>
/// Searches for the specified term in the index.
/// </summary>
/// <param name="term">The term.</param>
public static HitCollection Search(string queryString, IEnumerable <Indexer> indexers, int maxResults)
{
foreach (Indexer ixr in indexers)
{
if (!ixr.indexExists ||
ixr.searcher == null)
{
throw new Exception(String.Format(Properties.Resources.IndexDoesNotExist, ixr.filePath));
}
}
HitCollection ret = new HitCollection();
SearchItem si = new SearchItem();
si.Hits = ret;
si.SearchRequest = queryString;
si.MaxResults = maxResults;
si.Errors = new Queue <Exception>();
int indexersNumber = 0;
// I can't really be sure about the thread safety of Lucene
try
{
lock (typeof(Indexer))
{
foreach (Indexer ixr in indexers)
{
indexersNumber++;
int i = 0;
while (ixr.searchRunning &&
i < 30)
{
Thread.Sleep(100);
i++;
}
if (i >= 30)
{
throw new Exception(Properties.Resources.FailedStartingSearch);
}
ixr.searchRunning = true;
}
foreach (Indexer ixr in indexers)
{
ThreadPool.QueueUserWorkItem(ixr.Search, si);
}
foreach (Indexer ixr in indexers)
{
int i = 0;
while (ixr.searchRunning &&
i < 30)
{
Thread.Sleep(100);
i++;
}
if (i >= 30)
{
throw new Exception(Properties.Resources.FailedFinishingSearch);
}
}
}
}
catch (Exception ex)
{
lock (si.Errors)
{
si.Errors.Enqueue(ex);
}
}
StringCollection sc = new StringCollection();
lock (si.Errors)
{
while (si.Errors.Count > 0)
{
Exception ex = si.Errors.Dequeue();
if (!sc.Contains(ex.Message))
{
sc.Add(ex.Message);
}
}
}
StringBuilder sb = new StringBuilder();
foreach (string message in sc)
{
sb.AppendLine(message);
}
ret.ErrorMessages = sb.Length > 0 ? sb.ToString() : String.Empty;
if (indexersNumber > 1)
{
PageInfo[] arr = new PageInfo[ret.Count];
for (int i = 0; i < ret.Count; i++)
{
arr[i] = ret[i];
}
Array.Sort <PageInfo>(arr,
delegate(PageInfo a, PageInfo b)
{
return(a.Score < b.Score ? 1 : (a.Score > b.Score ? -1 : 0));
});
ret.Clear();
foreach (PageInfo pi in arr)
{
ret.Add(pi);
}
}
return(ret);
}