/// <inheritdoc/> public void Delete() { try { PersistentStorageHelper.RemoveFile(this.FullPath); } catch (Exception ex) { PersistentStorageEventSource.Log.Warning($"Deletion of file blob {this.FullPath} has failed.", ex); } }
/// <inheritdoc/> public IEnumerable <IPersistentBlob> GetBlobs() { var retentionDeadline = DateTime.UtcNow - TimeSpan.FromMilliseconds(this.retentionPeriodInMilliseconds); foreach (var file in Directory.EnumerateFiles(this.directoryPath, "*.blob", SearchOption.TopDirectoryOnly).OrderByDescending(f => f)) { DateTime fileDateTime = PersistentStorageHelper.GetDateTimeFromBlobName(file); if (fileDateTime > retentionDeadline) { yield return(new FileBlob(file)); } } }
private bool CheckStorageSize() { var size = PersistentStorageHelper.GetDirectorySize(); if (size >= this.maxSizeInBytes) { // TODO: check accuracy of size reporting. PersistentStorageEventSource.Log.Warning($"Persistent storage max capacity has been reached. Currently at {size / 1024} KB. " + "Please consider increasing the value of storage max size in exporter config."); return(false); } return(true); }
private void OnMaintenanceEvent(object source, ElapsedEventArgs e) { try { if (!Directory.Exists(this.directoryPath)) { Directory.CreateDirectory(this.directoryPath); } } catch (Exception ex) { PersistentStorageEventSource.Log.Error($"Error creating directory {this.directoryPath}", ex); return; } PersistentStorageHelper.RemoveExpiredBlobs(this.directoryPath, this.retentionPeriodInMilliseconds, this.writeTimeoutInMilliseconds); }
/// <inheritdoc/> public IPersistentBlob CreateBlob(byte[] buffer, int leasePeriodMilliseconds = 0) { if (!this.CheckStorageSize()) { return(null); } try { var blobFilePath = Path.Combine(this.directoryPath, PersistentStorageHelper.GetUniqueFileName(".blob")); var blob = new FileBlob(blobFilePath); return(blob.Write(buffer, leasePeriodMilliseconds)); } catch (Exception ex) { PersistentStorageEventSource.Log.Warning("CreateBlob has failed.", ex); return(null); } }
/// <summary> /// Initializes a new instance of the <see cref="FileStorage"/> /// class. /// </summary> /// <param name="path"> /// Sets file storage folder location where blobs are stored. /// </param> /// <param name="maxSizeInBytes"> /// Maximum allowed storage folder size. /// Default is 50 MB. /// </param> /// <param name="maintenancePeriodInMilliseconds"> /// Maintenance event runs at specified interval. /// Removes expired leases and blobs that exceed retention period. /// Default is 2 minutes. /// </param> /// <param name="retentionPeriodInMilliseconds"> /// Retention period in milliseconds for the blob. /// Default is 2 days. /// </param> /// <param name="writeTimeoutInMilliseconds"> /// Controls the timeout when writing a buffer to blob. /// Default is 1 minute. /// </param> public FileStorage( string path, long maxSizeInBytes = 52428800, int maintenancePeriodInMilliseconds = 120000, long retentionPeriodInMilliseconds = 172800000, int writeTimeoutInMilliseconds = 60000) { if (path == null) { throw new ArgumentNullException(nameof(path)); } // TODO: Validate time period values this.directoryPath = PersistentStorageHelper.CreateSubdirectory(path); this.maxSizeInBytes = maxSizeInBytes; this.retentionPeriodInMilliseconds = retentionPeriodInMilliseconds; this.writeTimeoutInMilliseconds = writeTimeoutInMilliseconds; this.maintenanceTimer = new Timer(maintenancePeriodInMilliseconds); this.maintenanceTimer.Elapsed += this.OnMaintenanceEvent; this.maintenanceTimer.AutoReset = true; this.maintenanceTimer.Enabled = true; }
/// <inheritdoc/> public IPersistentBlob Write(byte[] buffer, int leasePeriodMilliseconds = 0) { string path = this.FullPath + ".tmp"; try { PersistentStorageHelper.WriteAllBytes(path, buffer); if (leasePeriodMilliseconds > 0) { var timestamp = DateTime.UtcNow + TimeSpan.FromMilliseconds(leasePeriodMilliseconds); this.FullPath += $"@{timestamp:yyyy-MM-ddTHHmmss.fffffffZ}.lock"; } File.Move(path, this.FullPath); } catch (Exception ex) { PersistentStorageEventSource.Log.Warning($"Writing a blob to file {path} has failed.", ex); return(null); } return(this); }