예제 #1
0
        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();
                        }
                    }
                }
            }
        }
예제 #2
0
        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);

                    //проверку на признак удаления делать не нужно, т.к. ссылка слабая
                }
            }
        }
예제 #3
0
        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();
            }
        }