blob: f355648f31a66a1f43e9fb440e37fa9c0e99a017 [file] [log] [blame]
#region Apache License
//
// 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.
//
#endregion
using System;
using System.IO;
namespace log4net.Appender.Rolling
{
/// <summary>
/// A implementation of the <see cref="IRollingCondition"/> interface that rolls
/// the file cronologically.
/// </summary>
/// <author>Dominik Psenner</author>
public class CronRollingCondition : IRollingCondition
{
#region Public Instance Constructors
public CronRollingCondition()
: this("*", "*", "*", "*", "*")
{
}
public CronRollingCondition(string dow, string month, string day, string hour, string minute)
{
Dow = TryParse(dow);
Month = TryParse(month);
Day = TryParse(day);
Hour = TryParse(hour);
Minute = TryParse(minute);
}
#endregion
#region Protected Instance Properties
protected Tuple<int?, MatchType> Dow { get; private set; }
protected Tuple<int?, MatchType> Month { get; private set; }
protected Tuple<int?, MatchType> Day { get; private set; }
protected Tuple<int?, MatchType> Hour { get; private set; }
protected Tuple<int?, MatchType> Minute { get; private set; }
#endregion
#region Private Instance Properties
private ulong last_rolled = 0;
#endregion
#region Protected Inner Classes
protected enum MatchType
{
Nothing,
Exact,
Remainder,
}
#endregion
#region Protected Static Methods
/// <summary>
/// This method parses a string to match any of these:
/// i
/// *
/// */i
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
static protected Tuple<int?, MatchType> TryParse(string input)
{
// trim input and strip empty spaces
string inputParsed = input.Trim().Replace(" ", "").Replace("\t", "");
// match a remainder: */c
if (inputParsed.StartsWith("*/") || inputParsed.StartsWith(@"*\"))
{
// strip first two chars
inputParsed = inputParsed.Substring(2);
// parse the remainder
int i = -1;
if (int.TryParse(inputParsed, out i))
{
return Tuple.Create<int?, MatchType>(i, MatchType.Remainder);
}
}
else if (inputParsed.StartsWith("*")) // match anything: *
{
return Tuple.Create<int?, MatchType>(null, MatchType.Nothing);
}
else // match one specific numer: i
{
int i = -1;
if (int.TryParse(inputParsed, out i))
{
return Tuple.Create<int?, MatchType>(i, MatchType.Exact);
}
}
// throw exception by default
throw new FormatException(string.Format("The input string '{0}' could not be parsed to a valid format.", input));
}
#endregion
#region Implementation of IRollingCondition
public bool IsMet(string file)
{
return IsMet(DateTime.Now);
}
private static ulong GetUniqueIndex(DateTime now)
{
ulong result = (ulong)now.DayOfWeek;
result <<= 3;
result += (ulong)now.Month;
result <<= 4;
result += (ulong)now.Day;
result <<= 5;
result += (ulong)now.Hour;
result <<= 5;
result += (ulong)now.Minute;
return result;
}
#endregion
#region Public Methods
public bool IsMet(DateTime now)
{
Console.WriteLine("test {0}", now);
// check only every minute
// we can skip the check as we checked this minute already
// and if we don't we may run into the situation to roll a file twice
if (GetUniqueIndex(now) == last_rolled)
{
Console.WriteLine(" skipped");
return false;
}
if (!IsMet(Dow, (int)now.DayOfWeek))
{
return false;
}
if (!IsMet(Month, now.Month))
{
return false;
}
if (!IsMet(Day, now.Day))
{
return false;
}
if (!IsMet(Hour, now.Hour))
{
return false;
}
if (!IsMet(Minute, now.Minute))
{
return false;
}
last_rolled = GetUniqueIndex(now);
return true;
}
#endregion
#region Private Methods
private bool IsMet(Tuple<int?, MatchType> match, int item)
{
switch (match.Item2)
{
case MatchType.Exact:
Console.WriteLine(" {0} != {1} == {2}", match.Item1.Value, item, match.Item1.Value != item);
if (match.Item1.Value != item)
{
return false;
}
break;
case MatchType.Remainder:
// special case: */0, the division through 0 is undefined; this match should pass
if (match.Item1.Value == 0)
{
Console.WriteLine("{0} % 0 == 0", item);
return false;
}
else
{
Console.WriteLine(" {0} % {1} == {2}", item, match.Item1.Value, item % match.Item1.Value);
if (item % match.Item1.Value != 0)
{
return false;
}
}
break;
}
return true;
}
#endregion
/// <summary>
/// Converts the given rolling condition to a nicely formatted string representation.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return string.Format("{0} {1} {2} {3} {4}", Dow, Month, Day, Hour, Minute);
}
}
}