public void Execute()
{
using (LogContext.WithDatabase(context.DatabaseName))
{
Init();
var name = GetType().Name;
var workComment = "WORK BY " + name;
bool isIdle = false;
while (context.RunIndexing)
{
bool foundWork;
try
{
bool onlyFoundIdleWork;
foundWork = ExecuteIndexing(isIdle, out onlyFoundIdleWork);
if (foundWork && onlyFoundIdleWork == false)
{
isIdle = false;
}
while (context.RunIndexing) // we want to drain all of the pending tasks before the next run
{
if (ExecuteTasks() == false)
{
break;
}
foundWork = true;
}
}
catch (OutOfMemoryException oome)
{
foundWork = true;
HandleOutOfMemoryException(oome);
}
catch (AggregateException ae)
{
foundWork = true;
var actual = ae.ExtractSingleInnerException();
var oome = actual as OutOfMemoryException;
if (oome == null)
{
if (IsEsentOutOfMemory(actual))
{
autoTuner.OutOfMemoryExceptionHappened();
}
Log.ErrorException("Failed to execute indexing", ae);
}
else
{
HandleOutOfMemoryException(oome);
}
}
catch (OperationCanceledException)
{
Log.Info("Got rude cancellation of indexing as a result of shutdown, aborting current indexing run");
return;
}
catch (Exception e)
{
foundWork = true; // we want to keep on trying, anyway, not wait for the timeout or more work
Log.ErrorException("Failed to execute indexing", e);
if (IsEsentOutOfMemory(e))
{
autoTuner.OutOfMemoryExceptionHappened();
}
}
if (foundWork == false && context.RunIndexing)
{
isIdle = context.WaitForWork(context.Configuration.TimeToWaitBeforeRunningIdleIndexes, ref workCounter, () =>
{
try
{
FlushIndexes();
}
catch (Exception e)
{
Log.WarnException("Could not flush indexes properly", e);
}
}, name);
}
else // notify the tasks executer that it has work to do
{
context.ShouldNotifyAboutWork(() => workComment);
context.NotifyAboutWork();
}
}
Dispose();
}
}