use of org.nuxeo.drive.service.FileSystemChangeSummary in project nuxeo-drive-server by nuxeo.
the class AuditChangeFinderTestSuite method testFindChanges.
@Test
public void testFindChanges() throws Exception {
List<FileSystemItemChange> changes;
DocumentModel doc1;
DocumentModel doc2;
DocumentModel doc3;
DocumentModel docToCopy;
DocumentModel copiedDoc;
DocumentModel docToVersion;
commitAndWaitForAsyncCompletion();
try {
// No sync roots
changes = getChanges();
assertNotNull(changes);
assertTrue(changes.isEmpty());
log.trace("Sync roots for Administrator");
nuxeoDriveManager.registerSynchronizationRoot(session.getPrincipal(), folder1, session);
nuxeoDriveManager.registerSynchronizationRoot(session.getPrincipal(), folder2, session);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
// Get changes for Administrator
changes = getChanges();
// Root registration events
assertEquals(2, changes.size());
log.trace("Create 3 documents, only 2 in sync roots");
doc1 = session.createDocumentModel("/folder1", "doc1", "File");
doc1.setPropertyValue("file:content", new StringBlob("The content of file 1."));
doc1 = session.createDocument(doc1);
doc2 = session.createDocumentModel("/folder2", "doc2", "File");
doc2.setPropertyValue("file:content", new StringBlob("The content of file 2."));
doc2 = session.createDocument(doc2);
doc3 = session.createDocumentModel("/folder3", "doc3", "File");
doc3.setPropertyValue("file:content", new StringBlob("The content of file 3."));
doc3 = session.createDocument(doc3);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(2, changes.size());
Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
expectedChanges.add(new SimpleFileSystemItemChange(doc2.getId(), "documentCreated", "test"));
expectedChanges.add(new SimpleFileSystemItemChange(doc1.getId(), "documentCreated", "test"));
assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
// No changes since last successful sync
changes = getChanges();
assertTrue(changes.isEmpty());
log.trace("Update both synchronized documents and unsynchronize a root");
doc1.setPropertyValue("file:content", new StringBlob("The content of file 1, updated."));
session.saveDocument(doc1);
doc2.setPropertyValue("file:content", new StringBlob("The content of file 2, updated."));
session.saveDocument(doc2);
nuxeoDriveManager.unregisterSynchronizationRoot(session.getPrincipal(), folder2, session);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(2, changes.size());
// The root unregistration is mapped to a fake deletion from the
// client's point of view
Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
expectedChanges.add(new SimpleFileSystemItemChange(folder2.getId(), "deleted", "test"));
expectedChanges.add(new SimpleFileSystemItemChange(doc1.getId(), "documentModified", "test"));
assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
log.trace("Delete a document with a lifecycle transition (trash)");
session.followTransition(doc1.getRef(), "delete");
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(1, changes.size());
assertEquals(new SimpleFileSystemItemChange(doc1.getId(), "deleted", "test", "test#" + doc1.getId()), toSimpleFileSystemItemChange(changes.get(0)));
log.trace("Restore a deleted document and move a document in a newly synchronized root");
session.followTransition(doc1.getRef(), "undelete");
session.move(doc3.getRef(), folder2.getRef(), null);
nuxeoDriveManager.registerSynchronizationRoot(session.getPrincipal(), folder2, session);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(3, changes.size());
Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
expectedChanges.add(new SimpleFileSystemItemChange(folder2.getId(), "rootRegistered", "test", "defaultSyncRootFolderItemFactory#test#" + folder2.getId()));
expectedChanges.add(new SimpleFileSystemItemChange(doc3.getId(), "documentMoved", "test"));
expectedChanges.add(new SimpleFileSystemItemChange(doc1.getId(), "lifecycle_transition_event", "test"));
assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
log.trace("Physical deletion without triggering the delete transition first");
session.removeDocument(doc3.getRef());
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(1, changes.size());
assertEquals(new SimpleFileSystemItemChange(doc3.getId(), "deleted", "test", "test#" + doc3.getId()), toSimpleFileSystemItemChange(changes.get(0)));
log.trace("Create a doc and copy it from a sync root to another one");
docToCopy = session.createDocumentModel("/folder1", "docToCopy", "File");
docToCopy.setPropertyValue("file:content", new StringBlob("The content of file to copy."));
docToCopy = session.createDocument(docToCopy);
copiedDoc = session.copy(docToCopy.getRef(), folder2.getRef(), null);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(2, changes.size());
Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
expectedChanges.add(new SimpleFileSystemItemChange(copiedDoc.getId(), "documentCreatedByCopy", "test", "defaultFileSystemItemFactory#test#" + copiedDoc.getId(), "docToCopy"));
expectedChanges.add(new SimpleFileSystemItemChange(docToCopy.getId(), "documentCreated", "test", "defaultFileSystemItemFactory#test#" + docToCopy.getId(), "docToCopy"));
assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
log.trace("Remove file from a document, mapped to a fake deletion from the client's point of view");
doc1.setPropertyValue("file:content", null);
session.saveDocument(doc1);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(1, changes.size());
assertEquals(new SimpleFileSystemItemChange(doc1.getId(), "deleted", "test"), toSimpleFileSystemItemChange(changes.get(0)));
log.trace("Move a doc from a sync root to another sync root");
session.move(copiedDoc.getRef(), folder1.getRef(), null);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(1, changes.size());
assertEquals(new SimpleFileSystemItemChange(copiedDoc.getId(), "documentMoved", "test"), toSimpleFileSystemItemChange(changes.get(0)));
log.trace("Move a doc from a sync root to a non synchronized folder");
session.move(copiedDoc.getRef(), folder3.getRef(), null);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(1, changes.size());
assertEquals(new SimpleFileSystemItemChange(copiedDoc.getId(), "deleted", "test"), toSimpleFileSystemItemChange(changes.get(0)));
log.trace("Create a doc, create a version of it, update doc and restore the version");
docToVersion = session.createDocumentModel("/folder1", "docToVersion", "File");
docToVersion.setPropertyValue("file:content", new StringBlob("The content of file to version."));
docToVersion = session.createDocument(docToVersion);
docToVersion.putContextData(VersioningService.VERSIONING_OPTION, VersioningOption.MAJOR);
session.saveDocument(docToVersion);
docToVersion.setPropertyValue("file:content", new StringBlob("Updated content of the versioned file."));
session.saveDocument(docToVersion);
List<DocumentModel> versions = session.getVersions(docToVersion.getRef());
assertEquals(1, versions.size());
DocumentModel version = versions.get(0);
session.restoreToVersion(docToVersion.getRef(), version.getRef());
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
// Expecting 4 (among which 3 distinct) changes:
// - documentRestored for docToVersion
// - documentModified for docToVersion (2 occurrences)
// - documentCreated for docToVersion
assertEquals(4, changes.size());
Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
expectedChanges.add(new SimpleFileSystemItemChange(docToVersion.getId(), "documentRestored"));
expectedChanges.add(new SimpleFileSystemItemChange(docToVersion.getId(), "documentModified"));
expectedChanges.add(new SimpleFileSystemItemChange(docToVersion.getId(), "documentCreated"));
assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
log.trace("Too many changes");
session.followTransition(doc1.getRef(), "delete");
session.followTransition(doc2.getRef(), "delete");
} finally {
commitAndWaitForAsyncCompletion();
}
Framework.getProperties().put("org.nuxeo.drive.document.change.limit", "1");
FileSystemChangeSummary changeSummary = getChangeSummary(session.getPrincipal());
assertEquals(true, changeSummary.getHasTooManyChanges());
}
use of org.nuxeo.drive.service.FileSystemChangeSummary in project nuxeo-drive-server by nuxeo.
the class TestGetChangeSummary method getChangeSummary.
/**
* Gets the changes summary for the user bound to the {@link #session} using the {@link NuxeoDriveGetChangeSummary}
* automation operation and updates the {@link #lastSyncDate} date.
*/
protected FileSystemChangeSummary getChangeSummary() throws Exception {
// Wait 1 second as the mock change finder relies on steps of 1 second
Thread.sleep(1000);
Blob changeSummaryJSON = (Blob) clientSession.newRequest(NuxeoDriveGetChangeSummary.ID).set("lastSyncDate", lastSyncDate).set("lastSyncActiveRootDefinitions", lastSyncActiveRoots).execute();
assertNotNull(changeSummaryJSON);
FileSystemChangeSummary changeSummary = mapper.readValue(changeSummaryJSON.getStream(), FileSystemChangeSummaryImpl.class);
assertNotNull(changeSummary);
lastSyncDate = changeSummary.getSyncDate();
lastSyncActiveRoots = changeSummary.getActiveSynchronizationRootDefinitions();
return changeSummary;
}
use of org.nuxeo.drive.service.FileSystemChangeSummary in project nuxeo-drive-server by nuxeo.
the class TestGetChangeSummaryMultiRepo method testGetDocumentChangesSummary.
@Test
public void testGetDocumentChangesSummary() throws Exception {
// Register 3 sync roots and create 3 documents: 2 in the 'test'
// repository, 1 in the 'other' repository
DocumentModel doc1;
DocumentModel doc2;
DocumentModel doc3;
Principal administrator = session.getPrincipal();
nuxeoDriveManager.registerSynchronizationRoot(administrator, folder1, session);
nuxeoDriveManager.registerSynchronizationRoot(administrator, folder2, session);
nuxeoDriveManager.registerSynchronizationRoot(administrator, folder3, otherSession);
doc1 = session.createDocumentModel("/folder1", "doc1", "File");
doc1.setPropertyValue("file:content", new StringBlob("The content of file 1."));
doc1 = session.createDocument(doc1);
doc2 = session.createDocumentModel("/folder2", "doc2", "File");
doc2.setPropertyValue("file:content", new StringBlob("The content of file 2."));
doc2 = session.createDocument(doc2);
doc3 = otherSession.createDocumentModel("/folder3", "doc3", "File");
doc3.setPropertyValue("file:content", new StringBlob("The content of file 3."));
doc3 = otherSession.createDocument(doc3);
TransactionHelper.commitOrRollbackTransaction();
TransactionHelper.startTransaction();
// Look in all repositories => should find 3 changes
FileSystemChangeSummary changeSummary = getChangeSummary();
List<FileSystemItemChange> docChanges = changeSummary.getFileSystemChanges();
assertEquals(3, docChanges.size());
Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
expectedChanges.add(new SimpleFileSystemItemChange(doc1.getId(), "documentChanged", "test"));
expectedChanges.add(new SimpleFileSystemItemChange(doc2.getId(), "documentChanged", "test"));
expectedChanges.add(new SimpleFileSystemItemChange(doc3.getId(), "documentChanged", "other"));
Set<SimpleFileSystemItemChange> changes = new HashSet<>();
docChanges.forEach(docChange -> {
changes.add(new SimpleFileSystemItemChange(docChange.getDocUuid(), docChange.getEventId(), docChange.getRepositoryId()));
assertNotNull(docChange.getFileSystemItem());
});
assertTrue(CollectionUtils.isEqualCollection(expectedChanges, changes));
assertEquals(Boolean.FALSE, changeSummary.getHasTooManyChanges());
// Update documents
doc1.setPropertyValue("dc:description", "Added description to doc1.");
doc2.setPropertyValue("dc:description", "Added description to doc1.");
doc3.setPropertyValue("dc:description", "Added description to doc1.");
session.saveDocument(doc1);
session.saveDocument(doc2);
otherSession.saveDocument(doc3);
TransactionHelper.commitOrRollbackTransaction();
TransactionHelper.startTransaction();
changeSummary = getChangeSummary();
docChanges = changeSummary.getFileSystemChanges();
assertEquals(3, docChanges.size());
}
use of org.nuxeo.drive.service.FileSystemChangeSummary in project nuxeo-drive-server by nuxeo.
the class NuxeoDriveGetChangeSummary method run.
@OperationMethod
public Blob run() throws IOException {
NuxeoDriveManager driveManager = Framework.getService(NuxeoDriveManager.class);
Map<String, Set<IdRef>> lastActiveRootRefs = RootDefinitionsHelper.parseRootDefinitions(lastSyncActiveRootDefinitions);
FileSystemChangeSummary docChangeSummary;
if (lastSyncDate >= 0) {
docChangeSummary = driveManager.getChangeSummary(ctx.getPrincipal(), lastActiveRootRefs, lastSyncDate);
} else {
docChangeSummary = driveManager.getChangeSummaryIntegerBounds(ctx.getPrincipal(), lastActiveRootRefs, lowerBound);
}
return Blobs.createJSONBlobFromValue(docChangeSummary);
}
use of org.nuxeo.drive.service.FileSystemChangeSummary in project nuxeo-drive-server by nuxeo.
the class NuxeoDriveManagerImpl method getChangeSummary.
protected FileSystemChangeSummary getChangeSummary(Principal principal, Map<String, Set<IdRef>> lastActiveRootRefs, Map<String, SynchronizationRoots> roots, Map<String, Set<String>> collectionSyncRootMemberIds, long lowerBound, boolean integerBounds) {
List<FileSystemItemChange> allChanges = new ArrayList<FileSystemItemChange>();
// Compute the list of all repositories to consider for the aggregate summary
Set<String> allRepositories = new TreeSet<String>();
allRepositories.addAll(roots.keySet());
allRepositories.addAll(lastActiveRootRefs.keySet());
allRepositories.addAll(collectionSyncRootMemberIds.keySet());
long syncDate;
long upperBound;
if (integerBounds) {
upperBound = changeFinder.getUpperBound(allRepositories);
// Truncate sync date to 0 milliseconds
syncDate = System.currentTimeMillis();
syncDate = syncDate - (syncDate % 1000);
} else {
upperBound = changeFinder.getCurrentDate();
syncDate = upperBound;
}
Boolean hasTooManyChanges = Boolean.FALSE;
int limit = Integer.parseInt(Framework.getProperty(DOCUMENT_CHANGE_LIMIT_PROPERTY, "1000"));
if (!allRepositories.isEmpty() && lowerBound >= 0 && upperBound > lowerBound) {
for (String repositoryName : allRepositories) {
try (CloseableCoreSession session = CoreInstance.openCoreSession(repositoryName, principal)) {
// Get document changes
Set<IdRef> lastRefs = lastActiveRootRefs.get(repositoryName);
if (lastRefs == null) {
lastRefs = Collections.emptySet();
}
SynchronizationRoots activeRoots = roots.get(repositoryName);
if (activeRoots == null) {
activeRoots = SynchronizationRoots.getEmptyRoots(repositoryName);
}
Set<String> repoCollectionSyncRootMemberIds = collectionSyncRootMemberIds.get(repositoryName);
if (repoCollectionSyncRootMemberIds == null) {
repoCollectionSyncRootMemberIds = Collections.emptySet();
}
if (log.isDebugEnabled()) {
log.debug(String.format("Start: getting FileSystemItem changes for repository %s / user %s between %s and %s with activeRoots = %s", repositoryName, principal.getName(), lowerBound, upperBound, activeRoots.getPaths()));
}
List<FileSystemItemChange> changes;
if (integerBounds) {
changes = changeFinder.getFileSystemChangesIntegerBounds(session, lastRefs, activeRoots, repoCollectionSyncRootMemberIds, lowerBound, upperBound, limit);
} else {
changes = changeFinder.getFileSystemChanges(session, lastRefs, activeRoots, lowerBound, upperBound, limit);
}
allChanges.addAll(changes);
} catch (TooManyChangesException e) {
hasTooManyChanges = Boolean.TRUE;
allChanges.clear();
break;
}
}
}
// Send back to the client the list of currently active roots to be able
// to efficiently detect root unregistration events for the next
// incremental change summary
Map<String, Set<IdRef>> activeRootRefs = new HashMap<String, Set<IdRef>>();
for (Map.Entry<String, SynchronizationRoots> rootsEntry : roots.entrySet()) {
activeRootRefs.put(rootsEntry.getKey(), rootsEntry.getValue().getRefs());
}
FileSystemChangeSummary summary = new FileSystemChangeSummaryImpl(allChanges, activeRootRefs, syncDate, upperBound, hasTooManyChanges);
if (log.isDebugEnabled()) {
log.debug(String.format("End: getting %d FileSystemItem changes for user %s between %s and %s with activeRoots = %s -> %s", allChanges.size(), principal.getName(), lowerBound, upperBound, roots, summary));
}
return summary;
}
Aggregations