2020-05-20 15:14:44 +00:00
/ *
*
* ( c ) Copyright Ascensio System Limited 2010 - 2020
*
* This program is freeware . You can redistribute it and / or modify it under the terms of the GNU
* General Public License ( GPL ) version 3 as published by the Free Software Foundation ( https : //www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7 ( a ) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non - infringement of any third - party rights .
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY ; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE . For more details , see GNU GPL at https : //www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales @onlyoffice . com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices , as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3 ( b ) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software . If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons , you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute .
* Pursuant to Section 7 § 3 ( e ) we decline to grant you any rights under trademark law for use of our trademarks .
*
* /
using System ;
using System.Linq ;
2021-08-31 09:40:28 +00:00
using System.Threading ;
2020-05-28 13:28:51 +00:00
using ASC.Common ;
2020-05-20 15:14:44 +00:00
using ASC.Common.Logging ;
2021-08-31 09:40:28 +00:00
using ASC.Data.Backup.Storage ;
using ASC.Files.Core ;
using Microsoft.Extensions.DependencyInjection ;
2020-05-20 15:14:44 +00:00
using Microsoft.Extensions.Options ;
namespace ASC.Data.Backup.Service
2021-08-31 09:40:28 +00:00
{
2020-10-19 15:53:15 +00:00
[Scope]
2020-05-29 14:50:39 +00:00
internal class BackupCleanerHelperService
{
2021-08-31 09:40:28 +00:00
private readonly ILog log ;
private BackupRepository BackupRepository { get ; }
private BackupStorageFactory BackupStorageFactory { get ; }
public BackupCleanerHelperService (
IOptionsMonitor < ILog > options ,
BackupRepository backupRepository ,
2020-05-29 14:50:39 +00:00
BackupStorageFactory backupStorageFactory )
{
2021-08-31 09:40:28 +00:00
log = options . CurrentValue ;
BackupRepository = backupRepository ;
BackupStorageFactory = backupStorageFactory ;
2020-05-29 14:50:39 +00:00
}
internal void DeleteExpiredBackups ( BackupCleanerService backupCleanerService )
{
2021-08-31 09:40:28 +00:00
log . Debug ( "started to clean expired backups" ) ;
2020-05-29 14:50:39 +00:00
var backupsToRemove = BackupRepository . GetExpiredBackupRecords ( ) ;
log . DebugFormat ( "found {0} backups which are expired" , backupsToRemove . Count ) ;
if ( ! backupCleanerService . IsStarted ) return ;
foreach ( var scheduledBackups in BackupRepository . GetScheduledBackupRecords ( ) . GroupBy ( r = > r . TenantId ) )
{
if ( ! backupCleanerService . IsStarted ) return ;
var schedule = BackupRepository . GetBackupSchedule ( scheduledBackups . Key ) ;
if ( schedule ! = null )
{
var scheduledBackupsToRemove = scheduledBackups . OrderByDescending ( r = > r . CreatedOn ) . Skip ( schedule . BackupsStored ) . ToList ( ) ;
2022-01-18 13:54:24 +00:00
if ( scheduledBackupsToRemove . Count > 0 )
2020-05-29 14:50:39 +00:00
{
log . DebugFormat ( "only last {0} scheduled backup records are to keep for tenant {1} so {2} records must be removed" , schedule . BackupsStored , schedule . TenantId , scheduledBackupsToRemove . Count ) ;
backupsToRemove . AddRange ( scheduledBackupsToRemove ) ;
}
}
else
{
backupsToRemove . AddRange ( scheduledBackups ) ;
}
}
foreach ( var backupRecord in backupsToRemove )
{
if ( ! backupCleanerService . IsStarted ) return ;
try
{
var backupStorage = BackupStorageFactory . GetBackupStorage ( backupRecord ) ;
if ( backupStorage = = null ) continue ;
backupStorage . Delete ( backupRecord . StoragePath ) ;
BackupRepository . DeleteBackupRecord ( backupRecord . Id ) ;
2021-08-31 09:40:28 +00:00
}
catch ( ProviderInfoArgumentException error )
{
log . Warn ( "can't remove backup record " + backupRecord . Id , error ) ;
if ( DateTime . UtcNow > backupRecord . CreatedOn . AddMonths ( 6 ) )
{
BackupRepository . DeleteBackupRecord ( backupRecord . Id ) ;
}
2020-05-29 14:50:39 +00:00
}
catch ( Exception error )
{
2020-12-28 13:22:08 +00:00
log . Warn ( "can't remove backup record: " + backupRecord . Id , error ) ;
2020-05-29 14:50:39 +00:00
}
}
}
2021-08-31 09:40:28 +00:00
}
2020-10-26 13:38:21 +00:00
[Singletone(Additional = typeof(BackupCleanerServiceExtension))]
2020-05-20 15:14:44 +00:00
public class BackupCleanerService
{
private readonly object cleanerLock = new object ( ) ;
2020-05-29 14:50:39 +00:00
private Timer CleanTimer { get ; set ; }
internal bool IsStarted { get ; set ; }
private ILog Log { get ; set ; }
2021-08-31 09:40:28 +00:00
public TimeSpan Period { get ; set ; }
private IServiceProvider ServiceProvider { get ; set ; }
public BackupCleanerService (
IOptionsMonitor < ILog > options ,
2020-05-29 14:50:39 +00:00
IServiceProvider serviceProvider )
2021-08-31 09:40:28 +00:00
{
ServiceProvider = serviceProvider ;
2020-05-29 14:50:39 +00:00
Log = options . CurrentValue ;
2020-05-20 15:14:44 +00:00
Period = TimeSpan . FromMinutes ( 15 ) ;
}
public void Start ( )
{
2020-05-29 14:50:39 +00:00
if ( ! IsStarted & & Period > TimeSpan . Zero )
2020-05-20 15:14:44 +00:00
{
2020-05-29 14:50:39 +00:00
Log . Info ( "starting backup cleaner service..." ) ;
CleanTimer = new Timer ( _ = > DeleteExpiredBackups ( ) , null , TimeSpan . Zero , Period ) ;
Log . Info ( "backup cleaner service started" ) ;
IsStarted = true ;
2020-05-20 15:14:44 +00:00
}
}
public void Stop ( )
{
2020-05-29 14:50:39 +00:00
if ( IsStarted )
2020-05-20 15:14:44 +00:00
{
2020-05-29 14:50:39 +00:00
Log . Info ( "stopping backup cleaner service..." ) ;
if ( CleanTimer ! = null )
2020-05-20 15:14:44 +00:00
{
2020-05-29 14:50:39 +00:00
CleanTimer . Change ( Timeout . Infinite , Timeout . Infinite ) ;
CleanTimer . Dispose ( ) ;
CleanTimer = null ;
2020-05-20 15:14:44 +00:00
}
2020-05-29 14:50:39 +00:00
Log . Info ( "backup cleaner service stopped" ) ;
IsStarted = false ;
2020-05-20 15:14:44 +00:00
}
}
private void DeleteExpiredBackups ( )
{
if ( Monitor . TryEnter ( cleanerLock ) )
{
try
2021-08-31 09:40:28 +00:00
{
using var scope = ServiceProvider . CreateScope ( ) ;
var backupCleanerHelperService = scope . ServiceProvider . GetService < BackupCleanerHelperService > ( ) ;
2020-05-29 14:50:39 +00:00
backupCleanerHelperService . DeleteExpiredBackups ( this ) ;
2020-05-20 15:14:44 +00:00
}
catch ( Exception error )
{
2020-05-29 14:50:39 +00:00
Log . Error ( "error while cleaning expired backup records: {0}" , error ) ;
2020-05-20 15:14:44 +00:00
}
finally
{
Monitor . Exit ( cleanerLock ) ;
}
}
}
2021-08-31 09:40:28 +00:00
}
public class BackupCleanerServiceExtension
{
public static void Register ( DIHelper services )
{
services . TryAdd < BackupCleanerHelperService > ( ) ;
}
2020-05-20 15:14:44 +00:00
}
}