internal void Init() { //Debugger.Launch(); //1 - поднять настройку из бд this.BuildSettings(); //2 - добавляем настройку из конфига в метаданные if (this.ReplicationConfiguration.ConfigFolders.Count > 0) { foreach (ConfigReplicationFolder configFolder in this.ReplicationConfiguration.ConfigFolders) { //проверка существования настройки из конфига ReplicationFolder replicationFolder = this.GetReplicationFolder(configFolder); if (replicationFolder == null) { //папки репликации нет в метаданных, но есть в конфиге, нужно ее создать StorageNode sourceStorage = null; foreach (StorageNode node in _storageNodesByID.Values) { if (node.Host.ToLower() == configFolder.SourceNode.ToLower()) { sourceStorage = node; break; } } if (sourceStorage == null) { //1 - нет самого узла источника данных this.StartObserverThread(configFolder.SourceNode); } else { //2 - узел есть, создаем папку репликации bool justCreated; replicationFolder = this.EnsureReplicationFolder(sourceStorage, configFolder.Url, true, out justCreated); } } else { bool updateRequired = false; if (!replicationFolder.IsCurrentNodeSettings) { //если вдруг по каким-то причинам флаг сняли replicationFolder.IsCurrentNodeSettings = true; updateRequired = true; } if (replicationFolder.Deleted) { //восстановление настройки replicationFolder.Deleted = false; updateRequired = true; } if (updateRequired) { replicationFolder.Update(); } } } } //3 - проверяем настройку из бд, которая была текущей по конфигу //т.к. ее могли удалить foreach (Dictionary <string, ReplicationFolder> storageReplicationFolders in _replicationFolders.Values) { foreach (ReplicationFolder replicationFolder in storageReplicationFolders.Values) { //проверяем только текущую настройку, остальная может быть актуальной на других узлах if (replicationFolder.IsCurrentNodeSettings) { if (!this.ReplicationConfiguration.ContainsFolder(replicationFolder.Folder.Url)) { //в конфиге нет настройки из бд //помечаем ее в бд, как удаленную replicationFolder.Deleted = true; replicationFolder.Update(); } } } } }
private void UpdateSchemaItem(IReplicationSchema remoteSchema, IReplicationSchemaItem remoteSchemaItem) { if (remoteSchema == null) { throw new ArgumentNullException("remoteSchema"); } if (remoteSchemaItem == null) { throw new ArgumentNullException("remoteSchemaItem"); } bool forCurrentStorage = remoteSchemaItem.StorageID == this.Engine.CurrentNode.UniqueID; bool isStrongRelation = remoteSchemaItem.RelationType == ReplicationRelation.Strong; //хост хранилища может поменяться //ищем по UniqueID и если не совпадают хосты, то меняем хост //доверяем хосту, только от которого пришел ответ if (forCurrentStorage) { if (isStrongRelation) { //есть строгая ссылка на текущий узел, для узла, с которого пришел запрос. #region Обновление информации об узле bool justCreated; StorageNode remoteNode = this.EnsureNode(remoteSchema.StorageID, remoteSchema.Host, out justCreated); if (!justCreated) { //если узел уже был, то проверяем нужно ли обновить хост существующего узла if (remoteNode.Host.ToLower() != remoteSchema.Host.ToLower()) { lock (_updateStorageLocker) { if (remoteNode.Host.ToLower() != remoteSchema.Host.ToLower()) { remoteNode.Host = remoteSchema.Host.ToLower(); remoteNode.Update(); } } } } #endregion } } //если это STRONG признак, то создаем, если настройки нет foreach (string folderUrl in remoteSchemaItem.Folders) { if (isStrongRelation) { #region strong relation //настройка пришла непосредственно с узла схемы и на этом узле есть //если она предназначена для текущего узла, то создаем/снимаем признак удаленности if (forCurrentStorage) { //узел remote схемы bool justCreated; StorageNode remoteNode = this.EnsureNode(remoteSchema.StorageID, remoteSchema.Host, out justCreated); //получаем папку для репликации с remote узлом bool replicationFolderJustCreated; ReplicationFolder replicationFolder = this.EnsureReplicationFolder(remoteNode, folderUrl, false, out replicationFolderJustCreated); if (!replicationFolderJustCreated) { //если настройка существовала и была удалена, то восстанавливаем ее if (replicationFolder.Deleted) { replicationFolder.Deleted = false; replicationFolder.Update(); } } } else { //Strong ссылка на репликацию с 3-им (отличным от текущего) узлом, //смотрим если на текущем узле есть пересекающиеся папки, то добавляем weak настройку this.AddWeakRelation(remoteSchemaItem.StorageID, remoteSchemaItem.Name, folderUrl); } #endregion } else { if (forCurrentStorage) { //слабые ссылки на самого себя не надо восстанавливать continue; } //если это WEAK признак, то создаем, только если есть пересекающиеся настройки this.AddWeakRelation(remoteSchemaItem.StorageID, remoteSchemaItem.Name, folderUrl); //проверку на признак удаления делать не нужно, т.к. ссылка слабая } } }
private void ProcessRemoteFilesInternal(ReplicationFolder replicationFolder, Tuple <Guid, Guid>[] remoteFiles) { if (replicationFolder == null) { throw new ArgumentNullException("replicationFolder"); } if (remoteFiles == null || remoteFiles.Length == 0) { throw new ArgumentNullException("remoteFiles"); } //словарь существующих файлов. Dictionary <Guid, File> existsFiles = new Dictionary <Guid, File>(); Dictionary <string, byte> uniqueFileVersions = new Dictionary <string, byte>(); //формируем словарь существующих файлов и списков файлов, //которых не существует и которые необходимо реплицировать. List <RemoteFileInfo> filesToDownload = new List <RemoteFileInfo>(); foreach (Tuple <Guid, Guid> fileVersionInfo in remoteFiles) { Guid fileID = fileVersionInfo.Item1; Guid fileVersionID = fileVersionInfo.Item2; bool fileVersionExists = false; string key = string.Format("{0}_{1}", fileID, fileVersionID); if (uniqueFileVersions.ContainsKey(key)) { continue; } uniqueFileVersions.Add(key, 0); File file = null; try { file = this.Engine.GetFileInternal(replicationFolder.Folder.Url, fileID, null, false); } catch (Exception fileEx) { //таблицы с файлов может не быть. this.Logger.WriteMessage(fileEx.ToString(), LogLevel.Error); } if (file != null) { fileVersionExists = file.VersionUniqueID == fileVersionID || file.GetVersion(fileVersionID, false) != null; if (!existsFiles.ContainsKey(file.UniqueID)) { existsFiles.Add(file.UniqueID, file); } } if (!fileVersionExists) { filesToDownload.Add(new RemoteFileInfo(fileVersionInfo, replicationFolder.Folder)); } } if (filesToDownload.Count == 0) { return; } DateTime?lastSync = null; try { foreach (RemoteFileInfo remoteFileInfo in filesToDownload) { IRemoteFile remoteFile = null; try { remoteFile = this.Transport.GetReplicationFile( replicationFolder.SourceStorage, remoteFileInfo.Folder.Url, remoteFileInfo.UniqueID, remoteFileInfo.VersionID); if (remoteFile == null) { throw new Exception(string.Format("Не удалось получить файла с идентификатором {0} с узла {1}", remoteFileInfo.UniqueID, replicationFolder.SourceStorage.Host)); } StorageNode typedNode = (StorageNode)replicationFolder.SourceStorage; remoteFile.CreatedStorageNode = typedNode.Metadata; var stream = remoteFile.Stream; if (stream == null) { throw new Exception(string.Format("Не удалось получить поток файла с идентификатором {0} с узла {1}", remoteFileInfo.UniqueID, replicationFolder.SourceStorage.Host)); } File localFile = null; if (existsFiles.ContainsKey(remoteFile.UniqueID)) { localFile = existsFiles[remoteFile.UniqueID]; } if (localFile == null) { //загружаем новый файл IFileVersionMetadata fileVersion = this.Engine.DataAdapter.WriteRemoteFile(replicationFolder.TypedFolder.Metadata, remoteFile); localFile = new File(this.Engine, replicationFolder.Folder, fileVersion.FileMetadata); //добавляем в коллекцию существующих на текущем узле existsFiles.Add(localFile.UniqueID, localFile); } else { //файл уже существует, добавляем только новую версию файла this.Engine.DataAdapter.WriteRemoteFileVersion(localFile.Metadata, remoteFile); } //обновляем дату синхронизации по дате создания версии lastSync = remoteFile.TimeCreated; } catch (Exception remoteFileEx) { throw new Exception(string.Format("Ошибка при репликации файла {0} с узла {1}", remoteFileInfo.UniqueID, replicationFolder.SourceStorage.Host), remoteFileEx); } finally { try { if (remoteFile != null && remoteFile.Stream != null) { remoteFile.Stream.Dispose(); } } catch (Exception innerEx) { this.Logger.WriteMessage(innerEx.ToString(), LogLevel.Error); } } } } catch (Exception ex) { this.Logger.WriteMessage(ex.ToString(), LogLevel.Error); } if (lastSync.HasValue) { replicationFolder.Metadata.LastSyncTime = lastSync.Value; replicationFolder.Update(); } }