Newer
Older
using System;
using System.IO;
using System.Xml.Serialization;
namespace ATXCommon.Serializables
/// <summary>
/// AutoTx service status class.
/// </summary>
[Serializable]
public class ServiceStatus
{
[XmlIgnore] private string _storageFile; // remember where we came from
[XmlIgnore] private ServiceConfig _config;
[XmlIgnore] public string ValidationWarnings;
[XmlIgnore] private static readonly Logger Log = LogManager.GetCurrentClassLogger();
private DateTime _lastStatusUpdate;
private DateTime _lastStorageNotification;
private DateTime _lastAdminNotification;
private DateTime _lastGraceNotification;
private string _limitReason;
private string _currentTransferSrc;
private string _currentTargetTmp;
private bool _transferInProgress;
private bool _serviceSuspended;
private bool _cleanShutdown;
private long _currentTransferSize;
/// <summary>
/// Timestamp indicating when the status has been updated last ("heartbeat").
/// </summary>
[XmlElement("LastStatusUpdate", DataType = "dateTime")]
public DateTime LastStatusUpdate {
get { return _lastStatusUpdate; }
set { _lastStatusUpdate = value; }
}
/// <summary>
/// Timestamp indicating when the last storage notification has been sent.
/// </summary>
[XmlElement("LastStorageNotification", DataType = "dateTime")]
public DateTime LastStorageNotification {
get { return _lastStorageNotification; }
set {
_lastStorageNotification = value;
Serialize();
}
}
/// <summary>
/// Timestamp indicating when the last admin notification has been sent.
/// </summary>
[XmlElement("LastAdminNotification", DataType = "dateTime")]
public DateTime LastAdminNotification {
get { return _lastAdminNotification; }
set {
_lastAdminNotification = value;
Serialize();
}
}
/// <summary>
/// Timestamp indicating when the last notification on expired folders has been sent.
/// </summary>
[XmlElement("LastGraceNotification", DataType = "dateTime")]
public DateTime LastGraceNotification {
get { return _lastGraceNotification; }
set {
_lastGraceNotification = value;
Serialize();
}
}
/// <summary>
/// String indicating why the service is currently suspended (empty if not suspended).
/// </summary>
public string LimitReason {
get { return _limitReason; }
set {
_limitReason = value;
Log.Trace("LimitReason was updated ({0}).", value);
/// <summary>
/// The full path to the folder currently being transferred.
/// </summary>
public string CurrentTransferSrc {
get { return _currentTransferSrc; }
set {
_currentTransferSrc = value;
Log.Trace("CurrentTransferSrc was updated ({0}).", value);
Serialize();
}
}
/// <summary>
/// The name of the temporary folder being used for the currently running transfer,
/// relative to "DestinationDirectory\TmpTransferDir" (i.e. the target username). See also
/// <seealso cref="CurrentTargetTmpFull"/> on details for assembling the full path.
/// </summary>
public string CurrentTargetTmp {
get { return _currentTargetTmp; }
set {
_currentTargetTmp = value;
Log.Trace("CurrentTargetTmp was updated ({0}).", value);
Serialize();
}
}
/// <summary>
/// Flag indicating whether the service is currently suspended.
/// </summary>
public bool ServiceSuspended {
get { return _serviceSuspended; }
set {
_serviceSuspended = value;
Log.Trace("ServiceSuspended was updated ({0}).", value);
Serialize();
}
}
/// <summary>
/// Flag indicating whether a transfer is currently running.
/// </summary>
public bool TransferInProgress {
get { return _transferInProgress; }
set {
_transferInProgress = value;
Log.Trace("FilecopyFinished was updated ({0}).", value);
Serialize();
}
}
/// <summary>
/// Indicates whether the service was cleanly shut down (false while the service is running).
/// </summary>
public bool CleanShutdown {
get { return _cleanShutdown; }
set {
_cleanShutdown = value;
Serialize();
}
}
/// <summary>
/// The full size of the current transfer in bytes.
/// </summary>
public long CurrentTransferSize {
get { return _currentTransferSize; }
set {
_currentTransferSize = value;
Log.Trace("CurrentTransferSize was updated ({0}).", value);
Serialize();
}
}
public ServiceStatus() {
_currentTransferSrc = "";
_currentTargetTmp = "";
_transferInProgress = false;
}
public void Serialize() {
/* During de-serialization, the setter methods get called as well but
* we should not serialize until the deserialization has completed.
* As the storage file name will only be set after this, it is sufficient
* to test for this (plus, we can't serialize anyway without it).
*/
if (_storageFile == null) {
Log.Trace("File name for XML serialization is not set, doing nothing!");
Log.Trace("Serializing status...");
// update the timestamp:
LastStatusUpdate = DateTime.Now;
try {
var xs = new XmlSerializer(GetType());
var writer = File.CreateText(_storageFile);
xs.Serialize(writer, this);
writer.Flush();
writer.Close();
}
catch (Exception ex) {
Log.Error("Error in Serialize(): {0}", ex.Message);
Log.Trace("Finished serializing [{0}].", _storageFile);
}
public static ServiceStatus Deserialize(string file, ServiceConfig config) {
Log.Trace("Trying to deserialize status XML file [{0}].", file);
ServiceStatus status;
var xs = new XmlSerializer(typeof(ServiceStatus));
try {
var reader = File.OpenText(file);
status = (ServiceStatus) xs.Deserialize(reader);
reader.Close();
Log.Trace("Finished deserializing service status XML file.");
}
catch (Exception) {
// if reading the status XML fails, we return an empty (new) one
status = new ServiceStatus();
Log.Warn("Deserializing [{0}] failed, creating new status using defauls.", file);
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
}
status._config = config;
ValidateStatus(status);
// now set the storage filename:
status._storageFile = file;
return status;
}
private static void ValidateStatus(ServiceStatus s) {
// CurrentTransferSrc
if (s.CurrentTransferSrc.Length > 0
&& !Directory.Exists(s.CurrentTransferSrc)) {
s.ValidationWarnings += " - found non-existing source path of an unfinished " +
"transfer: " + s.CurrentTransferSrc + "\n";
s.CurrentTransferSrc = "";
}
// CurrentTargetTmp
var currentTargetTmpPath = Path.Combine(s._config.DestinationDirectory,
s._config.TmpTransferDir,
s.CurrentTargetTmp);
if (s.CurrentTargetTmp.Length > 0
&& !Directory.Exists(currentTargetTmpPath)) {
s.ValidationWarnings += " - found non-existing temporary path of an " +
"unfinished transfer: " + currentTargetTmpPath + "\n";
s.CurrentTargetTmp = "";
}
}
/// <summary>
/// Generate a human-readable sumary of the current transfer.
/// </summary>
/// <returns>A string with details on the transfer.</returns>
public string Summary() {
return
"CurrentTransferSrc: " + CurrentTransferSrc + "\n" +
"CurrentTargetTmp: " + CurrentTargetTmp + "\n" +
"TransferInProgress: " + TransferInProgress + "\n" +
"CurrentTransferSize: " + CurrentTransferSize + "\n" +
"LastStatusUpdate: " +
LastStatusUpdate.ToString("yyyy-MM-dd HH:mm:ss") + "\n" +
"LastStorageNotification: " +
LastStorageNotification.ToString("yyyy-MM-dd HH:mm:ss") + "\n" +
"LastAdminNotification: " +
LastAdminNotification.ToString("yyyy-MM-dd HH:mm:ss") + "\n" +
"LastGraceNotification: " +
LastGraceNotification.ToString("yyyy-MM-dd HH:mm:ss") + "\n";
}
/// <summary>
/// Helper method to generate the full path of the current temp directory.
/// </summary>
/// <returns>A string with the path to the last tmp dir.</returns>
public string CurrentTargetTmpFull() {
return Path.Combine(_config.DestinationDirectory,
_config.TmpTransferDir,
_currentTargetTmp);
}