示例#1
0
        public async Task ExecuteAsync(IPluginJobContext context)
        {
            if (!CliUtils.ParseArgs(_options, context.Args))
            {
                return;
            }

            if (_isHelp)
            {
                PrintUsage();
                return;
            }

            if (string.IsNullOrEmpty(_directory))
            {
                await WriteUtils.PrintErrorAsync("Backup folder name not specified: --directory");

                return;
            }

            var oldTreeInfo = new TreeInfo(_settingsManager, _directory);
            var newTreeInfo = new TreeInfo(_settingsManager, Folder);

            if (!DirectoryUtils.IsDirectoryExists(oldTreeInfo.DirectoryPath))
            {
                await WriteUtils.PrintErrorAsync($"The backup folder does not exist: {oldTreeInfo.DirectoryPath}");

                return;
            }
            DirectoryUtils.CreateDirectoryIfNotExists(newTreeInfo.DirectoryPath);

            _updateService.Load(oldTreeInfo, newTreeInfo);

            await Console.Out.WriteLineAsync($"Backup folder: {oldTreeInfo.DirectoryPath}, Update folder: {newTreeInfo.DirectoryPath}, Update to SSCMS version: {_settingsManager.Version}");

            var oldTableNames = TranslateUtils.JsonDeserialize <List <string> >(await FileUtils.ReadTextAsync(oldTreeInfo.TablesFilePath, Encoding.UTF8));
            var newTableNames = new List <string>();

            await WriteUtils.PrintRowLineAsync();

            await WriteUtils.PrintRowAsync("Backup table name", "Update table Name", "Count");

            await WriteUtils.PrintRowLineAsync();

            var siteIdList = new List <int>();
            var tableNames = new List <string>();

            UpdateUtils.LoadSites(_settingsManager, oldTreeInfo, siteIdList, tableNames);

            var table = new TableContentConverter(_settingsManager);

            var splitSiteTableDict = new Dictionary <int, TableInfo>();

            if (_contentSplit)
            {
                var converter = table.GetSplitConverter();
                foreach (var siteId in siteIdList)
                {
                    splitSiteTableDict.Add(siteId, new TableInfo
                    {
                        Columns    = converter.NewColumns,
                        TotalCount = 0,
                        RowFiles   = new List <string>()
                    });
                }
            }

            foreach (var oldTableName in oldTableNames)
            {
                var oldMetadataFilePath = oldTreeInfo.GetTableMetadataFilePath(oldTableName);

                if (!FileUtils.IsFileExists(oldMetadataFilePath))
                {
                    continue;
                }

                var oldTableInfo = TranslateUtils.JsonDeserialize <TableInfo>(await FileUtils.ReadTextAsync(oldMetadataFilePath, Encoding.UTF8));

                if (ListUtils.ContainsIgnoreCase(tableNames, oldTableName))
                {
                    if (_contentSplit)
                    {
                        var converter = table.GetConverter(oldTableName, oldTableInfo.Columns);

                        await _updateService.UpdateSplitContentsTableInfoAsync(splitSiteTableDict, siteIdList, oldTableName,
                                                                               oldTableInfo, converter);
                    }
                    else
                    {
                        var converter = table.GetConverter(oldTableName, oldTableInfo.Columns);
                        var tuple     = await _updateService.GetNewTableInfoAsync(oldTableName, oldTableInfo, converter);

                        if (tuple != null)
                        {
                            newTableNames.Add(tuple.Item1);

                            await FileUtils.WriteTextAsync(newTreeInfo.GetTableMetadataFilePath(tuple.Item1), TranslateUtils.JsonSerialize(tuple.Item2));
                        }
                    }
                }
                else
                {
                    var tuple = await _updateService.UpdateTableInfoAsync(oldTableName, oldTableInfo);

                    if (tuple != null)
                    {
                        newTableNames.Add(tuple.Item1);

                        await FileUtils.WriteTextAsync(newTreeInfo.GetTableMetadataFilePath(tuple.Item1), TranslateUtils.JsonSerialize(tuple.Item2));
                    }
                }
            }

            if (_contentSplit)
            {
                foreach (var siteId in siteIdList)
                {
                    var siteTableInfo = splitSiteTableDict[siteId];
                    var siteTableName = UpdateUtils.GetSplitContentTableName(siteId);
                    newTableNames.Add(siteTableName);

                    await FileUtils.WriteTextAsync(newTreeInfo.GetTableMetadataFilePath(siteTableName), TranslateUtils.JsonSerialize(siteTableInfo));
                }

                await UpdateUtils.UpdateSitesSplitTableNameAsync(_databaseManager, newTreeInfo, splitSiteTableDict);
            }

            await FileUtils.WriteTextAsync(newTreeInfo.TablesFilePath, TranslateUtils.JsonSerialize(newTableNames));

            await WriteUtils.PrintRowLineAsync();

            await WriteUtils.PrintSuccessAsync("Update the backup data to the new version successfully!");
        }
示例#2
0
        public static async Task Backup(ISettingsManager settingsManager, IDatabaseManager databaseManager, List <string> includes, List <string> excludes, int maxRows, TreeInfo treeInfo, string errorLogFilePath)
        {
            var allTableNames = await settingsManager.Database.GetTableNamesAsync();

            var tableNames = new List <string>();

            foreach (var tableName in allTableNames)
            {
                if (includes != null && !ListUtils.ContainsIgnoreCase(includes, tableName))
                {
                    continue;
                }
                if (ListUtils.ContainsIgnoreCase(excludes, tableName))
                {
                    continue;
                }
                if (ListUtils.ContainsIgnoreCase(tableNames, tableName))
                {
                    continue;
                }
                tableNames.Add(tableName);
            }

            await FileUtils.WriteTextAsync(treeInfo.TablesFilePath, TranslateUtils.JsonSerialize(tableNames));

            await WriteUtils.PrintRowLineAsync();

            await WriteUtils.PrintRowAsync("Backup table name", "Count");

            await WriteUtils.PrintRowLineAsync();

            foreach (var tableName in tableNames)
            {
                try
                {
                    var columns = await settingsManager.Database.GetTableColumnsAsync(tableName);

                    var repository = new Repository(settingsManager.Database, tableName, columns);

                    var tableInfo = new TableInfo
                    {
                        Columns    = repository.TableColumns,
                        TotalCount = await repository.CountAsync(),
                        RowFiles   = new List <string>()
                    };

                    if (maxRows > 0 && tableInfo.TotalCount > maxRows)
                    {
                        tableInfo.TotalCount = maxRows;
                    }

                    await WriteUtils.PrintRowAsync(tableName, tableInfo.TotalCount.ToString("#,0"));

                    var identityColumnName =
                        await settingsManager.Database.AddIdentityColumnIdIfNotExistsAsync(tableName, tableInfo.Columns);

                    if (tableInfo.TotalCount > 0)
                    {
                        var current = 1;
                        if (tableInfo.TotalCount > CliConstants.PageSize)
                        {
                            var pageCount = (int)Math.Ceiling((double)tableInfo.TotalCount / CliConstants.PageSize);

                            using (var progress = new ProgressBar())
                            {
                                for (; current <= pageCount; current++)
                                {
                                    progress.Report((double)(current - 1) / pageCount);

                                    var fileName = $"{current}.json";
                                    tableInfo.RowFiles.Add(fileName);
                                    var offset = (current - 1) * CliConstants.PageSize;
                                    var limit  = tableInfo.TotalCount - offset < CliConstants.PageSize
                                        ? tableInfo.TotalCount - offset
                                        : CliConstants.PageSize;

                                    var rows = await databaseManager.GetPageObjectsAsync(tableName, identityColumnName, offset,
                                                                                         limit);

                                    await FileUtils.WriteTextAsync(
                                        treeInfo.GetTableContentFilePath(tableName, fileName),
                                        TranslateUtils.JsonSerialize(rows));
                                }
                            }
                        }
                        else
                        {
                            var fileName = $"{current}.json";
                            tableInfo.RowFiles.Add(fileName);
                            var rows = await databaseManager.GetObjectsAsync(tableName);

                            await FileUtils.WriteTextAsync(treeInfo.GetTableContentFilePath(tableName, fileName),
                                                           TranslateUtils.JsonSerialize(rows));
                        }
                    }

                    await FileUtils.WriteTextAsync(treeInfo.GetTableMetadataFilePath(tableName),
                                                   TranslateUtils.JsonSerialize(tableInfo));
                }
                catch (Exception ex)
                {
                    await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo
                    {
                        Exception = ex,
                        DateTime  = DateTime.Now,
                        Detail    = tableName
                    });
                }
            }
        }
示例#3
0
        public async Task <Tuple <string, TableInfo> > GetNewTableInfoAsync(string oldTableName, TableInfo oldTableInfo, ConvertInfo converter)
        {
            if (converter == null)
            {
                converter = new ConvertInfo();
            }

            if (converter.IsAbandon)
            {
                await WriteUtils.PrintRowAsync(oldTableName, "Abandon", "--");

                return(null);
            }

            if (string.IsNullOrEmpty(converter.NewTableName))
            {
                converter.NewTableName = oldTableName;
            }
            if (converter.NewColumns == null || converter.NewColumns.Count == 0)
            {
                converter.NewColumns = oldTableInfo.Columns;
            }

            var newTableInfo = new TableInfo
            {
                Columns    = converter.NewColumns,
                TotalCount = oldTableInfo.TotalCount,
                RowFiles   = oldTableInfo.RowFiles
            };

            await WriteUtils.PrintRowAsync(oldTableName, converter.NewTableName, oldTableInfo.TotalCount.ToString("#,0"));

            if (oldTableInfo.RowFiles.Count > 0)
            {
                var i = 0;
                using (var progress = new ProgressBar())
                {
                    foreach (var fileName in oldTableInfo.RowFiles)
                    {
                        progress.Report((double)i++ / oldTableInfo.RowFiles.Count);

                        var oldFilePath = OldTreeInfo.GetTableContentFilePath(oldTableName, fileName);
                        var newFilePath = NewTreeInfo.GetTableContentFilePath(converter.NewTableName, fileName);

                        if (converter.ConvertKeyDict != null)
                        {
                            var oldRows =
                                TranslateUtils.JsonDeserialize <List <JObject> >(await FileUtils.ReadTextAsync(oldFilePath, Encoding.UTF8));

                            var newRows = UpdateUtils.UpdateRows(oldRows, converter.ConvertKeyDict, converter.ConvertValueDict, converter.Process);

                            await FileUtils.WriteTextAsync(newFilePath, TranslateUtils.JsonSerialize(newRows));
                        }
                        else
                        {
                            FileUtils.CopyFile(oldFilePath, newFilePath);
                        }
                    }
                }
            }

            return(new Tuple <string, TableInfo>(converter.NewTableName, newTableInfo));
        }
示例#4
0
        public async Task UpdateSplitContentsTableInfoAsync(Dictionary <int, TableInfo> splitSiteTableDict, List <int> siteIdList, string oldTableName, TableInfo oldTableInfo, ConvertInfo converter)
        {
            if (converter == null)
            {
                converter = new ConvertInfo();
            }

            if (converter.IsAbandon)
            {
                await WriteUtils.PrintRowAsync(oldTableName, "Abandon", "--");

                return;
            }

            if (converter.NewColumns == null || converter.NewColumns.Count == 0)
            {
                converter.NewColumns = oldTableInfo.Columns;
            }

            await WriteUtils.PrintRowAsync(oldTableName, "#split-content#", oldTableInfo.TotalCount.ToString("#,0"));

            if (oldTableInfo.RowFiles.Count > 0)
            {
                var i = 0;
                using var progress = new ProgressBar();
                foreach (var fileName in oldTableInfo.RowFiles)
                {
                    progress.Report((double)i++ / oldTableInfo.RowFiles.Count);

                    var newRows = new List <Dictionary <string, object> >();

                    var oldFilePath = OldTreeInfo.GetTableContentFilePath(oldTableName, fileName);

                    var oldRows =
                        TranslateUtils.JsonDeserialize <List <JObject> >(await FileUtils.ReadTextAsync(oldFilePath, Encoding.UTF8));

                    newRows.AddRange(UpdateUtils.UpdateRows(oldRows, converter.ConvertKeyDict, converter.ConvertValueDict, converter.Process));

                    var siteIdWithRows = new Dictionary <int, List <Dictionary <string, object> > >();
                    foreach (var siteId in siteIdList)
                    {
                        siteIdWithRows.Add(siteId, new List <Dictionary <string, object> >());
                    }

                    foreach (var newRow in newRows)
                    {
                        if (newRow.ContainsKey(nameof(Content.SiteId)))
                        {
                            var siteId = Convert.ToInt32(newRow[nameof(Content.SiteId)]);
                            if (siteIdList.Contains(siteId))
                            {
                                var rows = siteIdWithRows[siteId];
                                rows.Add(newRow);
                            }
                        }
                    }

                    foreach (var siteId in siteIdList)
                    {
                        var siteRows      = siteIdWithRows[siteId];
                        var siteTableName = UpdateUtils.GetSplitContentTableName(siteId);

                        var siteTableInfo = splitSiteTableDict[siteId];
                        siteTableInfo.TotalCount += siteRows.Count;

                        foreach (var tableColumn in converter.NewColumns)
                        {
                            if (!siteTableInfo.Columns.Any(t => StringUtils.EqualsIgnoreCase(t.AttributeName, tableColumn.AttributeName)))
                            {
                                siteTableInfo.Columns.Add(tableColumn);
                            }
                        }

                        if (siteRows.Count > 0)
                        {
                            var siteTableFileName = $"{siteTableInfo.RowFiles.Count + 1}.json";
                            siteTableInfo.RowFiles.Add(siteTableFileName);
                            var filePath = NewTreeInfo.GetTableContentFilePath(siteTableName, siteTableFileName);
                            await FileUtils.WriteTextAsync(filePath, TranslateUtils.JsonSerialize(siteRows));
                        }
                    }
                }
            }
        }
示例#5
0
        public async Task <List <string> > RestoreAsync(List <string> includes, List <string> excludes, string tablesFilePath, TreeInfo treeInfo, string errorLogFilePath)
        {
            var tableNames =
                TranslateUtils.JsonDeserialize <List <string> >(await FileUtils.ReadTextAsync(tablesFilePath, Encoding.UTF8));
            var errorTableNames = new List <string>();

            foreach (var tableName in tableNames)
            {
                try
                {
                    if (includes != null)
                    {
                        if (!ListUtils.ContainsIgnoreCase(includes, tableName))
                        {
                            continue;
                        }
                    }

                    if (excludes != null)
                    {
                        if (ListUtils.ContainsIgnoreCase(excludes, tableName))
                        {
                            continue;
                        }
                    }

                    var metadataFilePath = treeInfo.GetTableMetadataFilePath(tableName);

                    if (!FileUtils.IsFileExists(metadataFilePath))
                    {
                        continue;
                    }

                    var tableInfo =
                        TranslateUtils.JsonDeserialize <TableInfo>(
                            await FileUtils.ReadTextAsync(metadataFilePath, Encoding.UTF8));

                    await WriteUtils.PrintRowAsync(tableName, tableInfo.TotalCount.ToString("#,0"));

                    if (await _settingsManager.Database.IsTableExistsAsync(tableName))
                    {
                        await _settingsManager.Database.DropTableAsync(tableName);
                    }

                    await _settingsManager.Database.CreateTableAsync(tableName, tableInfo.Columns);

                    if (tableInfo.RowFiles.Count > 0)
                    {
                        using var progress = new ProgressBar();
                        for (var i = 0; i < tableInfo.RowFiles.Count; i++)
                        {
                            progress.Report((double)i / tableInfo.RowFiles.Count);

                            var fileName = tableInfo.RowFiles[i];

                            var objects = TranslateUtils.JsonDeserialize <List <JObject> >(
                                await FileUtils.ReadTextAsync(treeInfo.GetTableContentFilePath(tableName, fileName), Encoding.UTF8));

                            try
                            {
                                var repository = new Repository(_settingsManager.Database, tableName,
                                                                tableInfo.Columns);
                                await repository.BulkInsertAsync(objects);
                            }
                            catch (Exception exception)
                            {
                                errorTableNames.Add(tableName);
                                await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo
                                {
                                    DateTime  = DateTime.Now,
                                    Detail    = $"插入表 {tableName}, 文件名 {fileName}",
                                    Exception = exception
                                });
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    errorTableNames.Add(tableName);
                    await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo
                    {
                        DateTime  = DateTime.Now,
                        Detail    = $"插入表 {tableName}",
                        Exception = ex
                    });
                }
            }

            await WriteUtils.PrintRowLineAsync();

            return(errorTableNames);

            //if (!dataOnly)
            //{
            //    // 恢复后同步表,确保内容辅助表字段与系统一致
            //    await _databaseManager.SyncDatabaseAsync();
            //    //await _databaseManager.SyncContentTablesAsync();
            //    await _configRepository.UpdateConfigVersionAsync(_settingsManager.Version);
            //}
        }
示例#6
0
        public async Task ExecuteAsync(IPluginJobContext context)
        {
            if (!CliUtils.ParseArgs(_options, context.Args))
            {
                return;
            }

            if (_isHelp)
            {
                PrintUsage();
                return;
            }

            if (string.IsNullOrEmpty(_directory))
            {
                await WriteUtils.PrintErrorAsync("Restore folder name not specified: --directory");

                return;
            }

            var treeInfo = new TreeInfo(_settingsManager, _directory);

            if (!DirectoryUtils.IsDirectoryExists(treeInfo.DirectoryPath))
            {
                await WriteUtils.PrintErrorAsync($"恢复数据的文件夹 {treeInfo.DirectoryPath} 不存在");

                return;
            }

            var tablesFilePath = treeInfo.TablesFilePath;

            if (!FileUtils.IsFileExists(tablesFilePath))
            {
                await WriteUtils.PrintErrorAsync($"恢复文件 {treeInfo.TablesFilePath} 不存在");

                return;
            }

            var configPath = CliUtils.GetConfigPath(_settingsManager);

            if (!FileUtils.IsFileExists(configPath))
            {
                await WriteUtils.PrintErrorAsync($"The sscms.json file does not exist: {configPath}");

                return;
            }

            //WebConfigUtils.Load(_settingsManager.ContentRootPath, webConfigPath);

            //if (string.IsNullOrEmpty(WebConfigUtils.ConnectionString))
            //{
            //    await CliUtils.PrintErrorAsync($"{webConfigPath} 中数据库连接字符串 connectionString 未设置");
            //    return;
            //}

            //await Console.Out.WriteLineAsync($"数据库类型: {_settingsManager.Database.DatabaseType.GetValue()}");
            //await Console.Out.WriteLineAsync($"连接字符串: {WebConfigUtils.ConnectionString}");
            //await Console.Out.WriteLineAsync($"恢复文件夹: {treeInfo.DirectoryPath}");

            await Console.Out.WriteLineAsync($"Database type: {_settingsManager.Database.DatabaseType.GetDisplayName()}");

            await Console.Out.WriteLineAsync($"Database connection string: {_settingsManager.Database.ConnectionString}");

            await Console.Out.WriteLineAsync($"Restore folder: {treeInfo.DirectoryPath}");

            var(isConnectionWorks, errorMessage) = await _settingsManager.Database.IsConnectionWorksAsync();

            if (!isConnectionWorks)
            {
                await WriteUtils.PrintErrorAsync($"Unable to connect to database, error message:{errorMessage}");

                return;
            }

            //if (!_dataOnly)
            //{
            //    if (!await _configRepository.IsNeedInstallAsync())
            //    {
            //        await WriteUtils.PrintErrorAsync("The data could not be restored on the installed sscms database");
            //        return;
            //    }

            //    // 恢复前先创建表,确保系统在恢复的数据库中能够使用
            //    //await _databaseManager.CreateSiteServerTablesAsync();

            //    if (_settingsManager.DatabaseType == DatabaseType.SQLite)
            //    {
            //        var filePath = PathUtils.Combine(_settingsManager.ContentRootPath, Constants.DefaultLocalDbFileName);
            //        if (!FileUtils.IsFileExists(filePath))
            //        {
            //            await FileUtils.WriteTextAsync(filePath, string.Empty);
            //        }
            //    }

            //    await _databaseManager.SyncDatabaseAsync();
            //}

            await WriteUtils.PrintRowLineAsync();

            await WriteUtils.PrintRowAsync("Restore table name", "Count");

            await WriteUtils.PrintRowLineAsync();

            var errorLogFilePath = CliUtils.DeleteErrorLogFileIfExists(_settingsManager);

            var errorTableNames = await _restoreService.RestoreAsync(_includes, _excludes, tablesFilePath, treeInfo, errorLogFilePath);

            if (errorTableNames.Count == 0)
            {
                await WriteUtils.PrintSuccessAsync("restore database successfully!");
            }
            else
            {
                await WriteUtils.PrintErrorAsync($"Database restore failed and the following table was not successfully restored: {ListUtils.ToString(errorTableNames)}");
            }
        }