private bool HasFolderChanged(IFolder deletedIFolder)
            {
                // TODO Does not work if newly-created.

                // ChangeLog
                string lastTokenOnClient = database.GetChangeLogToken();
                string lastTokenOnServer = CmisUtils.GetChangeLogToken(session);

                if (lastTokenOnClient == lastTokenOnServer || lastTokenOnClient == null)
                {
                    return(false);
                }

                // TODO: Extract static code, because same code was writtern in SynchronizedFolder
                Config.Feature features = null;
                if (ConfigManager.CurrentConfig.GetFolder(repoInfo.Name) != null)
                {
                    features = ConfigManager.CurrentConfig.GetFolder(repoInfo.Name).SupportedFeatures;
                }
                int maxNumItems = (features != null && features.MaxNumberOfContentChanges != null) ?  // TODO if there are more items, either loop or force CrawlSync
                                  (int)features.MaxNumberOfContentChanges : 500;

                var changes = session.GetContentChanges(lastTokenOnClient, IsPropertyChangesSupported, maxNumItems);

                return(CheckInsideChange(deletedIFolder, changes));
            }
Exemple #2
0
            /// <summary>
            /// Synchronize using the ChangeLog feature of CMIS.
            /// Not all CMIS servers support this feature, so sometimes CrawlStrategy is used instead.
            /// </summary>
            private void ChangeLogSync(IFolder remoteFolder)
            {
                // Get last change log token on server side.
                session.Binding.GetRepositoryService().GetRepositoryInfos(null);    //  refresh
                string lastTokenOnServer = session.Binding.GetRepositoryService().GetRepositoryInfo(session.RepositoryInfo.Id, null).LatestChangeLogToken;

                // Get last change token that had been saved on client side.
                // TODO catch exception invalidArgument which means that changelog has been truncated and this token is not found anymore.
                string lastTokenOnClient = database.GetChangeLogToken();

                if (lastTokenOnClient == lastTokenOnServer)
                {
                    Logger.Debug("No change from remote, wait for the next time.");
                    return;
                }

                if (lastTokenOnClient == null)
                {
                    // Token is null, which means no sync has ever happened yet, so just sync everything from remote.
                    CrawlRemote(remoteFolder, repoinfo.TargetDirectory, null, null);

                    Logger.Info("Succeeded to sync from remote, update ChangeLog token: " + lastTokenOnServer);

                    database.SetChangeLogToken(lastTokenOnServer);
                }

                do
                {
                    Config.Feature f = null;
                    if (ConfigManager.CurrentConfig.getFolder(repoinfo.Name) != null)
                    {
                        f = ConfigManager.CurrentConfig.getFolder(repoinfo.Name).SupportedFeatures;
                    }
                    int maxNumItems = (f != null && f.MaxNumberOfContentChanges != null)? (int)f.MaxNumberOfContentChanges: 100;
                    // Check which files/folders have changed.
                    IChangeEvents changes = session.GetContentChanges(lastTokenOnClient, IsPropertyChangesSupported, maxNumItems);
                    // Replicate each change to the local side.
                    bool success = true;
                    foreach (IChangeEvent change in changes.ChangeEventList)
                    {
                        try
                        {
                            switch (change.ChangeType)
                            {
                            case ChangeType.Created:
                                Logger.Info("New remote object (" + change.ObjectId + ") found.");
                                goto case ChangeType.Updated;

                            case ChangeType.Updated:
                                if (change.ChangeType == ChangeType.Updated)
                                {
                                    Logger.Info("Remote object (" + change.ObjectId + ") has been changed remotely.");
                                }
                                success = ApplyRemoteChangeUpdate(change) && success;
                                break;

                            case ChangeType.Deleted:
                                Logger.Info("Remote object (" + change.ObjectId + ") has been deleted remotely.");
                                success = ApplyRemoteChangeDelete(change) && success;
                                break;

                            default:
                                break;
                            }
                        }
                        catch (Exception e)
                        {
                            Logger.Warn("Exception when apply the change: ", e);
                            success = false;
                        }
                    }

                    if (success)
                    {
                        // Save change log token locally.
                        if (changes.HasMoreItems == true)
                        {
                            lastTokenOnClient = changes.LatestChangeLogToken;
                        }
                        else
                        {
                            lastTokenOnClient = lastTokenOnServer;
                        }
                        Logger.Info("Sync the changes on server, update ChangeLog token: " + lastTokenOnClient);
                        database.SetChangeLogToken(lastTokenOnClient);
                        session.Binding.GetRepositoryService().GetRepositoryInfos(null);    //  refresh
                        lastTokenOnServer = session.Binding.GetRepositoryService().GetRepositoryInfo(session.RepositoryInfo.Id, null).LatestChangeLogToken;
                    }
                    else
                    {
                        Logger.Warn("Failure to sync the changes on server, force crawl sync from remote");
                        CrawlRemote(remoteFolder, repoinfo.TargetDirectory, null, null);
                        Logger.Info("Succeeded to sync from remote, update ChangeLog token: " + lastTokenOnServer);
                        database.SetChangeLogToken(lastTokenOnServer);
                        return;
                    }
                }while (!lastTokenOnServer.Equals(lastTokenOnClient));
            }
            /// <summary>
            /// Synchronize using the ChangeLog feature of CMIS to trigger CrawlStrategy.
            /// </summary>
            private bool ChangeLogThenCrawlSync(IFolder remoteFolder, string remotePath, string localFolder)
            {
                // Once in a while, run a crawl sync, to make up for any server-side ChangeLog bug.
                // The frequency of this is calculated based on the poll interval, so that:
                // Interval=5 seconds -> every 6 hours -> about every 2160 iterations
                // Interval=1 hours -> every 3 days -> about every 72 iterations
                // Thus a good formula is: nb of iterations = 1 + 263907 / (pollInterval + 117)
                double pollInterval = ConfigManager.CurrentConfig.GetFolder(repoInfo.Name).PollInterval;

                if (changeLogIterationCounter > 263907 / (pollInterval / 1000 + 117))
                {
                    Logger.Debug("It has been a while since the last crawl sync, so launching a crawl sync now.");
                    bool crawlSuccess = CrawlSyncAndUpdateChangeLogToken(remoteFolder, remotePath, localFolder);
                    changeLogIterationCounter = 0;
                    return(crawlSuccess);
                }
                else
                {
                    changeLogIterationCounter++;
                }

                // Calculate queryable number of changes.
                Config.Feature features = null;
                if (ConfigManager.CurrentConfig.GetFolder(repoInfo.Name) != null)
                {
                    features = ConfigManager.CurrentConfig.GetFolder(repoInfo.Name).SupportedFeatures;
                }
                int maxNumItems = (features != null && features.MaxNumberOfContentChanges != null) ?  // TODO if there are more items, either loop or force CrawlSync
                                  (int)features.MaxNumberOfContentChanges : 50;

                // Get last change token that had been saved on client side.
                string lastTokenOnClient = database.GetChangeLogToken();

                // Get last change log token on server side.
                string lastTokenOnServer = CmisUtils.GetChangeLogToken(session);

                if (lastTokenOnClient == lastTokenOnServer)
                {
                    Logger.DebugFormat("No changes to sync, tokens on server and client are equal: \"{0}\"", lastTokenOnClient);
                    return(true);
                }

                bool success = true;

                if (lastTokenOnClient == null)
                {
                    // Token is null, which means no sync has ever happened yet, so just sync everything from remote.
                    success &= CrawlRemote(remoteFolder, remotePath, repoInfo.TargetDirectory, new List <string>(), new List <string>());

                    Logger.Info("Synced from remote, updating ChangeLog token: " + lastTokenOnServer);
                    database.SetChangeLogToken(lastTokenOnServer);
                }

                // ChangeLog tokens are different, so checking changes is needed.
                var           currentChangeToken = lastTokenOnClient;
                IChangeEvents changes;

                do
                {
                    // Check which documents/folders have changed.
                    changes = session.GetContentChanges(currentChangeToken, IsPropertyChangesSupported, maxNumItems);

                    // First event was already processed previous. <- not true for single rename
                    var changeEvents = changes.ChangeEventList./*Where(p => p != changes.ChangeEventList.FirstOrDefault()).*/ ToList();

                    success &= CrawlChangeLogSyncAndUpdateChangeLogToken(changeEvents, remoteFolder, remotePath, localFolder);

                    // Save the token of the last of the changes we just consumed.
                    currentChangeToken = changes.LatestChangeLogToken;
                    database.SetChangeLogToken(currentChangeToken);
                }
                // Repeat if there were two many changes to fit in a single response.
                while (changes.HasMoreItems ?? false);

                database.SetChangeLogToken(lastTokenOnServer);
                return(success);
            }
Exemple #4
0
            /// <summary>
            /// Synchronize using the ChangeLog feature of CMIS to trigger CrawlStrategy.
            /// </summary>
            private void ChangeLogThenCrawlSync(IFolder remoteFolder, string remotePath, string localFolder)
            {
                // Once in a while, run a crawl sync, to make up for any server-side ChangeLog bug.
                // The frequency of this is calculated based on the poll interval, so that:
                // Interval=5 seconds -> every 6 hours -> about every 2160 iterations
                // Interval=1 hours -> every 3 days -> about every 72 iterations
                // Thus a good formula is: nb of iterations = 1 + 263907 / (pollInterval + 117)
                double pollInterval = ConfigManager.CurrentConfig.GetFolder(repoInfo.Name).PollInterval;

                if (changeLogIterationCounter > 263907 / (pollInterval / 1000 + 117))
                {
                    Logger.Debug("It has been a while since the last crawl sync, so launching a crawl sync now.");
                    CrawlSyncAndUpdateChangeLogToken(remoteFolder, remotePath, localFolder);
                    changeLogIterationCounter = 0;
                    return;
                }
                else
                {
                    changeLogIterationCounter++;
                }

                // Calculate queryable number of changes.
                Config.Feature features = null;
                if (ConfigManager.CurrentConfig.GetFolder(repoInfo.Name) != null)
                {
                    features = ConfigManager.CurrentConfig.GetFolder(repoInfo.Name).SupportedFeatures;
                }
                int maxNumItems = (features != null && features.MaxNumberOfContentChanges != null) ?  // TODO if there are more items, either loop or force CrawlSync
                                  (int)features.MaxNumberOfContentChanges : 100;

                IChangeEvents changes;

                // Get last change token that had been saved on client side.
                string lastTokenOnClient = database.GetChangeLogToken();

                // Get last change log token on server side.
                string lastTokenOnServer = CmisUtils.GetChangeLogToken(session);

                if (lastTokenOnClient == lastTokenOnServer)
                {
                    Logger.Debug("No changes to sync, tokens on server and client are equal: \"" + lastTokenOnClient + "\"");
                    return;
                }

                if (lastTokenOnClient == null)
                {
                    // Token is null, which means no sync has ever happened yet, so just sync everything from remote.
                    CrawlRemote(remoteFolder, remotePath, repoInfo.TargetDirectory, new List <string>(), new List <string>());

                    Logger.Info("Synced from remote, updating ChangeLog token: " + lastTokenOnServer);
                    database.SetChangeLogToken(lastTokenOnServer);
                }

                // ChangeLog tokens are different, so checking changes is needed.
                do
                {
                    // Check which documents/folders have changed.
                    changes = session.GetContentChanges(lastTokenOnClient, IsPropertyChangesSupported, maxNumItems);

                    // Apply changes.
                    foreach (IChangeEvent change in changes.ChangeEventList)
                    {
                        // Check whether change is applicable.
                        // For instance, we dont care about changes to non-synced folders.
                        if (ChangeIsApplicable(change))
                        {
                            // Launch a CrawlSync (which means syncing everything indistinctively).
                            CrawlSyncAndUpdateChangeLogToken(remoteFolder, remotePath, localFolder);

                            // A single CrawlSync takes care of all pending changes, so no need to analyze the rest of the changes.
                            // It will also update the last client-side ChangeLog token, more accurately than we can do here.
                            return;
                        }
                    }

                    // No applicable changes, update ChangeLog token.
                    lastTokenOnClient = changes.LatestChangeLogToken; // But dont save to database as latest server token is actually a later token.
                }
                // Repeat if there were two many changes to fit in a single response.
                // Only reached if none of the changes in this iteration were non-applicable.
                while (changes.HasMoreItems ?? false);

                database.SetChangeLogToken(lastTokenOnServer);
            }