/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Xml;
using Lucene.Net.Distributed;
using Lucene.Net.Distributed.Configuration;
namespace Lucene.Net.Distributed.Indexing
{
///
/// Definition of configurable search indexes managed by the
/// LuceneUpdater windows service.
///
/// An example configuration would look like the following:
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
public class IndexSets
{
private bool _bCompoundFile;
private string _strDeltaDirectory;
private IndexSet[] _arIndexSet;
///
/// Accessor method for the configurable master indexes.
///
public static IndexSets GetConfig
{
get { return (IndexSets)ConfigurationManager.GetSection("IndexSets"); }
}
///
/// Strongly-typed array of IndexSet objects as defined in a configuration section.
///
/// XmlNode definition for a given IndexSet
public void LoadIndexSetArray(XmlNode node)
{
XmlAttributeCollection attributeCollection = node.Attributes;
try
{
this._bCompoundFile = Convert.ToBoolean(attributeCollection["CompoundFile"].Value);
}
catch (Exception)
{
throw new ConfigurationErrorsException("CompoundFile invalid: " + Environment.NewLine + node.OuterXml);
}
try
{
this._strDeltaDirectory = attributeCollection["DeltaDirectory"].Value;
}
catch (Exception)
{
throw new ConfigurationErrorsException("DeltaDirectory invalid: " + Environment.NewLine + node.OuterXml);
}
if (node.ChildNodes.Count == 0)
throw new ConfigurationErrorsException("No indexset definitions found " + Environment.NewLine + node.OuterXml);
this._arIndexSet = new IndexSet[node.ChildNodes.Count];
int x=0;
foreach (XmlNode c in node.ChildNodes)
{
if (c.Name.ToLower()=="IndexSet")
{
IndexSet idxSet = new IndexSet(c);
this._arIndexSet[x] = idxSet;
x++;
}
}
}
///
/// Public constructor for IndexSets. An IndexSet is defined in XML configuration
/// and is loaded via a custom configuration handler.
///
public IndexSets()
{
}
///
/// Indicates if the indexes under configuration should be built in the Compound format.
///
public bool CompoundFile
{
get {return this._bCompoundFile;}
}
///
/// Filesystem location of where pending update IndexDocuments are retrieved.
///
public string DeltaDirectory
{
get {return this._strDeltaDirectory;}
}
///
/// Strongly-typed array of IndexSet objects as defined in a configuration section.
///
public IndexSet[] IndexSetArray
{
get {return this._arIndexSet;}
}
///
/// Returns an IndexSet object for a given IndexDocument id value
///
/// Id value of the IndexDocument
/// The IndexSet containing the referenced IndexDocument
public IndexSet GetIndexSet(int deleteId)
{
IndexSet getSet=null;
foreach(IndexSet idxSet in this._arIndexSet)
{
if ((deleteId>=idxSet.BottomId)&&(deleteId<=idxSet.TopId))
getSet=idxSet;
}
return getSet;
}
///
/// Queries the DeltaDirectory to access any IndexDocument files. All IndexDocuments
/// stored in the DeltaDirectory have been serialized to a file; the files are deserialized,
/// evaluated for their id value (idcolumn) and added to the pending additions for the associated
/// IndexSet.
///
/// Filesystem path to the DeltaDirectory
public void LoadIndexDocuments(string sourceDir)
{
DirectoryInfo oDirectoryInfo = new DirectoryInfo(sourceDir);
FileInfo[] arFiles = oDirectoryInfo.GetFiles("*.bin");
Array.Sort(arFiles, new FileNameComparer());
IndexSet idxSet;
foreach (FileInfo fi in arFiles)
{
FileStream fs = new FileStream(fi.FullName, FileMode.Open);
IndexDocument iDoc = (IndexDocument)IndexDocument.Formatter.Deserialize(fs);
idxSet = this.GetIndexSet(iDoc.RecordId);
if (idxSet != null)
{
idxSet.FileSystemDocuments.Add(fi.FullName);
if (idxSet.IndexDocuments.ContainsKey(iDoc.RecordId))
{
IndexDocument curDoc = (IndexDocument)idxSet.IndexDocuments[iDoc.RecordId];
idxSet.IndexDocuments.Add(iDoc.RecordId, iDoc);
}
else
idxSet.IndexDocuments.Add(iDoc.RecordId, iDoc);
}
else
{
//Handling exceptions -- write file out somewhere else?
if (ConfigurationManager.AppSettings["ExceptionsBasePath"] != null)
iDoc.Save(ConfigurationManager.AppSettings["ExceptionsBasePath"]);
}
fs.Close();
}
oDirectoryInfo=null;
arFiles=null;
}
///
/// Method to apply pending updates (additions & deletions) for all configured IndexSet objects.
///
public void ProcessIndexDocuments()
{
foreach(IndexSet idxSet in this._arIndexSet)
{
if (idxSet.IndexDocuments.Count>0)
{
idxSet.CurrentIndex.ProcessLocalIndexDeletes(idxSet.GetDeletionCollection());
idxSet.CurrentIndex.ProcessLocalIndexAdditions(idxSet.Analzyer, idxSet.Documents, this.CompoundFile);
}
}
}
///
/// Method to apply updated index files from master index to slave indexes
///
public void CopyUpdatedFiles()
{
Hashtable htUpdates = new Hashtable();
bool bCopy=false;
foreach (IndexSet idxSet in this._arIndexSet)
{
bCopy=false;
if (idxSet.CurrentIndex!=null && idxSet.CurrentIndex.CanCopy)
bCopy=idxSet.CurrentIndex.CopyIncremental();
if (bCopy && !htUpdates.ContainsKey(idxSet.CurrentIndex.StatusDirectory))
htUpdates.Add(idxSet.CurrentIndex.StatusDirectory, idxSet.CurrentIndex);
}
foreach(DictionaryEntry de in htUpdates)
{
string sTargetDir = de.Key.ToString();
CurrentIndex ci = (CurrentIndex)de.Value;
ci.UpdateRefresh();
}
}
///
/// Method to apply updated index files from master index to slave indexes
///
/// Hashtable of updated indexes
public Hashtable CopyAllFiles()
{
Hashtable htUpdates = new Hashtable();
bool bCopy = false;
foreach (IndexSet idxSet in this._arIndexSet)
{
bCopy = false;
if (idxSet.CurrentIndex != null && idxSet.CurrentIndex.CanCopy)
bCopy = idxSet.CurrentIndex.Copy();
if (bCopy && !htUpdates.ContainsKey(idxSet.CurrentIndex.StatusDirectory))
htUpdates.Add(idxSet.CurrentIndex.StatusDirectory, idxSet.CurrentIndex);
}
foreach (DictionaryEntry de in htUpdates)
{
string sTargetDir = de.Key.ToString();
CurrentIndex ci = (CurrentIndex)de.Value;
ci.UpdateRefresh();
}
return htUpdates;
}
///
/// Method to execute an index optimization for each configured IndexSet object
///
public void OptimizeIndexes()
{
foreach (IndexSet idxSet in this._arIndexSet)
idxSet.Optimize();
}
///
/// Method to finalize update process for each IndexSet object
///
public void CompleteUpdate()
{
foreach (IndexSet idxSet in this._arIndexSet)
{
if (idxSet.FileSystemDocuments.Count>0)
{
foreach(string s in idxSet.FileSystemDocuments)
{
FileInfo fi = new FileInfo(s);
fi.Delete();
}
idxSet.Reset();
}
}
}
}
}