Skip to content

Commit

Permalink
Added Local/FTP Directory Monitor
Browse files Browse the repository at this point in the history
Added CreateMissingFolders/CreateFolders
  • Loading branch information
claco committed Oct 29, 2008
1 parent 04d810c commit 576f06f
Show file tree
Hide file tree
Showing 11 changed files with 390 additions and 49 deletions.
98 changes: 84 additions & 14 deletions Siphon/Monitors/DataMonitor.vb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Imports System.Timers
Imports System.Collections.ObjectModel
Imports System.Timers
Imports log4net

''' <summary>
Expand All @@ -11,17 +12,20 @@ Public MustInherit Class DataMonitor
Private Shared ReadOnly Log As ILog = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod.DeclaringType)
Private _disposed As Boolean = False
Private _name As String = String.Empty
Private _processing As Boolean = False
Private _processor As IDataProcessor = Nothing
Private _schedule As IMonitorSchedule = Nothing
Private WithEvents _timer As System.Timers.Timer

''' <summary>
''' Creates a new DataMonitor instance.
''' </summary>
''' <param name="name">String. The friendly name for the monitor.</param>
''' <param name="processor">IDataProcessor. The processor to use to handle newly found data.</param>
''' <param name="schedule">IMonitorSchedule. The schedule used to detemrin when to look for new data.</param>
''' <remarks></remarks>
Protected Sub New(ByVal schedule As IMonitorSchedule, ByVal processor As IDataProcessor)
Protected Sub New(ByVal name As String, ByVal schedule As IMonitorSchedule, ByVal processor As IDataProcessor)
Me.Name = name.Trim
Me.Schedule = schedule
Me.Processor = processor
End Sub
Expand All @@ -32,7 +36,7 @@ Public MustInherit Class DataMonitor
''' <value></value>
''' <returns>String</returns>
''' <remarks></remarks>
Public Property Name() As String Implements IDataMonitor.Name
Public Overridable Property Name() As String Implements IDataMonitor.Name
Get
Return _name
End Get
Expand All @@ -41,6 +45,18 @@ Public MustInherit Class DataMonitor
End Set
End Property

''' <summary>
''' Gets flag indicating if the current monitor is processing new data.
''' </summary>
''' <value></value>
''' <returns>Boolean. True if the monitor is processing new data. False otherwise.</returns>
''' <remarks></remarks>
Public Overridable ReadOnly Property Processing() As Boolean
Get
Return _processing
End Get
End Property

''' <summary>
''' Gets/sets the processor to handle newly found data.
''' </summary>
Expand All @@ -60,7 +76,7 @@ Public MustInherit Class DataMonitor
''' Scans for new data and sends new data to the current processor.
''' </summary>
''' <remarks></remarks>
Public MustOverride Sub Scan() Implements IDataMonitor.Scan
Public MustOverride Function Scan() As Collection(Of Object) Implements IDataMonitor.Scan

''' <summary>
''' Starts monitoring for new data.
Expand All @@ -69,13 +85,28 @@ Public MustInherit Class DataMonitor
Public Overridable Sub Start() Implements IDataMonitor.Start
Log.InfoFormat("Starting Monitor {0}", Me.Name)

Dim start As DateTime = DateTime.Now
Dim nextEvent As DateTime = Me.Schedule.NextEvent(start)
Timer.Interval = Me.NextInterval
Timer.Start()
End Sub

Log.DebugFormat("Monitor Start Time {0}", start)
Log.DebugFormat("Next Monitor Scan {0}", nextEvent)
''' <summary>
''' Pauses data monitoring, usually while processing files.
''' </summary>
''' <remarks></remarks>
Public Overridable Sub Pause() Implements IDataMonitor.Pause
Log.InfoFormat("Pausing Monitor {0}", Me.Name)

Timer.Stop()
End Sub

Timer.Interval = (nextEvent - start).TotalMilliseconds
''' <summary>
''' Resumes data monitors, usually after processing new data.
''' </summary>
''' <remarks></remarks>
Public Overridable Sub [Resume]() Implements IDataMonitor.Resume
Log.InfoFormat("Resuming Monitor {0}", Me.Name)

Timer.Interval = Me.NextInterval
Timer.Start()
End Sub

Expand All @@ -84,9 +115,15 @@ Public MustInherit Class DataMonitor
''' </summary>
''' <remarks></remarks>
Public Overridable Sub [Stop]() Implements IDataMonitor.Stop
Log.InfoFormat("Stopping Monitor {0}", Me.Name)
If Timer.Enabled Then
Log.InfoFormat("Stopping Monitor {0}", Me.Name)

Timer.Stop()
If Me.Processing Then
Log.Debug("Waiting for processor to finish")
End If

Timer.Stop()
End If
End Sub

''' <summary>
Expand Down Expand Up @@ -145,9 +182,42 @@ Public MustInherit Class DataMonitor
GC.SuppressFinalize(Me)
End Sub

''' <summary>
''' Gets the next event from the schedule and sets the timers interval.
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Private Function NextInterval() As Integer
Dim start As DateTime = DateTime.Now
Dim nextEvent As DateTime = Me.Schedule.NextEvent(start)
Dim interval As Integer = (nextEvent - start).TotalMilliseconds

Log.DebugFormat("Monitor Start Time {0}", start)
Log.DebugFormat("Next Monitor Scan {0}", nextEvent)
Log.DebugFormat("Timer Interval {0}", interval)

Return interval
End Function

Private Sub _timer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles _timer.Elapsed
Me.Stop()
Me.Scan()
Me.Start()
Me.Pause()

Try
Dim items As Collection(Of Object) = Me.Scan
If items.Count > 0 Then
_processing = True
Log.DebugFormat("{0} {1}", Me.Name, _processing)
For Each item As Object In items
Me.Processor.Process(item)
Next
Log.Debug("POST Process")

_processing = False
End If
Catch ex As Exception
'Log.Debug("BOOM", ex)
End Try

Me.Resume()
End Sub
End Class
46 changes: 30 additions & 16 deletions Siphon/Monitors/DirectoryMonitor.vb
Original file line number Diff line number Diff line change
@@ -1,46 +1,52 @@
Imports System.IO
Imports log4net
Imports log4net

''' <summary>
''' Monitors a directory for new files.
''' </summary>
''' <remarks></remarks>
Public Class DirectoryMonitor
Public MustInherit Class DirectoryMonitor
Inherits DataMonitor
Implements IDirectoryMonitor

Private Shared ReadOnly Log As ILog = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod.DeclaringType)
Private Const DEFAULT_FILTER As String = "*"
Private _createMissingFolders As Boolean = False
Private _filter As String = DEFAULT_FILTER
Private _path As String = String.Empty

''' <summary>
''' Creates a new directory monitor.
''' </summary>
''' <param name="name">String. The friendly name for the monitor.</param>
''' <param name="path">String. The full path to the directory to be monitored.</param>
''' <param name="schedule">IMonitorSchedule. The schedule used to monitor the directory.</param>
''' <param name="processor">IDataProcessor. The data processor to use to process new files.</param>
''' <remarks></remarks>
Public Sub New(ByVal path As String, ByVal schedule As IMonitorSchedule, ByVal processor As IDataProcessor)
MyBase.New(schedule, processor)
Public Sub New(ByVal name As String, ByVal path As String, ByVal schedule As IMonitorSchedule, ByVal processor As IDataProcessor)
MyBase.New(name, schedule, processor)
Me.Path = path
End Sub

''' <summary>
''' Scans the specified directory for new files mathcing the specified filter.
''' Creates missing folders before starting the timer.
''' </summary>
''' <remarks></remarks>
Public Overrides Sub Scan()
Log.DebugFormat("Scanning {0} for {1}", Me.Path, Me.Filter)
Public MustOverride Sub CreateFolders()

Dim files() As String = Directory.GetFiles(Me.Path, Me.Filter, SearchOption.TopDirectoryOnly)
Log.DebugFormat("Found {0} files in {1}", files.Length, Me.Path)

For Each file As String In files
Log.DebugFormat("Processing {0}", file)
Me.Processor.Process(file)
Next
End Sub
''' <summary>
''' Gets/sets flag determining whether to create any missing folders when starting the monitor.
''' </summary>
''' <value></value>
''' <returns>Boolean</returns>
''' <remarks></remarks>
Public Overridable Property CreateMissingFolders() As Boolean
Get
Return _createMissingFolders
End Get
Set(ByVal value As Boolean)
_createMissingFolders = value
End Set
End Property

''' <summary>
''' Gets/sets the file filter to apply to the directory.
Expand Down Expand Up @@ -75,4 +81,12 @@ Public Class DirectoryMonitor
_path = value.Trim
End Set
End Property

Public Overrides Sub Start()
If Me.CreateMissingFolders Then
Me.CreateFolders()
End If

MyBase.Start()
End Sub
End Class
42 changes: 42 additions & 0 deletions Siphon/Monitors/FtpDirectoryMonitor.vb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
Imports System.Collections.ObjectModel
Imports System.IO
Imports log4net

Public Class FtpDirectoryMonitor
Inherits DirectoryMonitor

Private Shared ReadOnly Log As ILog = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod.DeclaringType)

''' <summary>
''' Creates a new directory monitor.
''' </summary>
''' <param name="name">String. The friendly name for the monitor.</param>
''' <param name="path">String. The full path to the directory to be monitored.</param>
''' <param name="schedule">IMonitorSchedule. The schedule used to monitor the directory.</param>
''' <param name="processor">IDataProcessor. The data processor to use to process new files.</param>
''' <remarks></remarks>
Public Sub New(ByVal name As String, ByVal path As String, ByVal schedule As IMonitorSchedule, ByVal processor As IDataProcessor)
MyBase.New(name, path, schedule, processor)
End Sub

''' <summary>
''' Create any missing folders during start.
''' </summary>
''' <remarks></remarks>
Public Overrides Sub CreateFolders()

End Sub

''' <summary>
''' Scans the specified directory for new files mathcing the specified filter.
''' </summary>
''' <remarks></remarks>
Public Overrides Function Scan() As Collection(Of Object)
Log.DebugFormat("Scanning {0} for {1}", Me.Path, Me.Filter)

Dim files() As String = Directory.GetFiles(Me.Path, Me.Filter, SearchOption.TopDirectoryOnly)
Log.DebugFormat("Found {0} files in {1}", files.Length, Me.Path)

Return New System.Collections.ObjectModel.Collection(Of Object)(files)
End Function
End Class
18 changes: 16 additions & 2 deletions Siphon/Monitors/IDataMonitor.vb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
''' <summary>
Imports System.Collections.ObjectModel

''' <summary>
''' Interface that defines a data monitoring instance.
''' </summary>
''' <remarks></remarks>
Expand All @@ -25,6 +27,18 @@ Public Interface IDataMonitor
''' <remarks></remarks>
Sub [Stop]()

''' <summary>
''' Pauses data monitoring, usually while processing files.
''' </summary>
''' <remarks></remarks>
Sub Pause()

''' <summary>
''' Resumes data monitors, usually after processing new data.
''' </summary>
''' <remarks></remarks>
Sub [Resume]()

''' <summary>
''' Gets/sets the data processor to use when new data is found.
''' </summary>
Expand All @@ -45,5 +59,5 @@ Public Interface IDataMonitor
''' Scans for new data and sends new data to the current processor.
''' </summary>
''' <remarks></remarks>
Sub Scan()
Function Scan() As Collection(Of Object)
End Interface
48 changes: 48 additions & 0 deletions Siphon/Monitors/LocalDirectoryMonitor.vb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
Imports System.Collections.ObjectModel
Imports System.IO
Imports log4net

Public Class LocalDirectoryMonitor
Inherits DirectoryMonitor

Private Shared ReadOnly Log As ILog = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod.DeclaringType)

''' <summary>
''' Creates a new directory monitor.
''' </summary>
''' <param name="name">String. The friendly name for the monitor.</param>
''' <param name="path">String. The full path to the directory to be monitored.</param>
''' <param name="schedule">IMonitorSchedule. The schedule used to monitor the directory.</param>
''' <param name="processor">IDataProcessor. The data processor to use to process new files.</param>
''' <remarks></remarks>
Public Sub New(ByVal name As String, ByVal path As String, ByVal schedule As IMonitorSchedule, ByVal processor As IDataProcessor)
MyBase.New(name, path, schedule, processor)
End Sub

''' <summary>
''' Create any missing folders during start.
''' </summary>
''' <remarks></remarks>
Public Overrides Sub CreateFolders()
If Me.CreateMissingFolders Then
If Not Directory.Exists(Me.Path) Then
Log.DebugFormat("Creating directory {0}", Me.Path)

Directory.CreateDirectory(Me.Path)
End If
End If
End Sub

''' <summary>
''' Scans the specified directory for new files mathcing the specified filter.
''' </summary>
''' <remarks></remarks>
Public Overrides Function Scan() As Collection(Of Object)
Log.DebugFormat("Scanning {0} for {1}", Me.Path, Me.Filter)

Dim files() As String = Directory.GetFiles(Me.Path, Me.Filter, SearchOption.TopDirectoryOnly)
Log.DebugFormat("Found {0} files in {1}", files.Length, Me.Path)

Return New System.Collections.ObjectModel.Collection(Of Object)(files)
End Function
End Class
5 changes: 4 additions & 1 deletion Siphon/Schedules/DailySchedule.vb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ Public Class DailySchedule
If tp > max Then
Log.WarnFormat("Skipping TimeSpan greater than 24 hours {0}", tp)
Else
If tp >= start.TimeOfDay Then
Log.DebugFormat("Time Span {0}", tp.ToString)
Log.DebugFormat("Start TimeOfDay {0}", start.TimeOfDay)

If tp >= start.TimeOfDay And (tp - start.TimeOfDay).TotalSeconds >= 1 Then
Return New DateTime(start.Year, start.Month, start.Day, tp.Hours, tp.Minutes, tp.Seconds)
End If
End If
Expand Down
2 changes: 2 additions & 0 deletions Siphon/Siphon.vbproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@
<ItemGroup>
<Compile Include="Monitors\DataMonitor.vb" />
<Compile Include="Monitors\DirectoryMonitor.vb" />
<Compile Include="Monitors\FtpDirectoryMonitor.vb" />
<Compile Include="Monitors\IDataMonitor.vb" />
<Compile Include="Monitors\LocalDirectoryMonitor.vb" />
<Compile Include="Processors\DataProcessor.vb" />
<Compile Include="Processors\IDataProcessor.vb" />
<Compile Include="Monitors\IDirectoryMonitor.vb" />
Expand Down

0 comments on commit 576f06f

Please sign in to comment.