Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save reference ID identical across all versions of a file #15778

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 23,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public abstract class CachingFileIdProvider implements FileIdProvider {
public class CachingFileIdProvider implements FileIdProvider {
private static final Logger log = LogManager.getLogger(CachingFileIdProvider.class);

private final LRUCache<SimplePathPredicate, String> cache
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 23,15 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public abstract class CachingVersionIdProvider implements VersionIdProvider {
public class CachingVersionIdProvider implements VersionIdProvider {
private static final Logger log = LogManager.getLogger(CachingVersionIdProvider.class);

private final LRUCache<SimplePathPredicate, String> cache
= LRUCache.build(PreferencesFactory.get().getLong("fileid.cache.size"));

private final Protocol.Case sensitivity;

protected CachingVersionIdProvider(final Protocol.Case sensitivity) {
public CachingVersionIdProvider(final Protocol.Case sensitivity) {
this.sensitivity = sensitivity;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 47,9 @@ public SDSAttributesAdapter(final SDSSession session) {
@Override
public PathAttributes toAttributes(final Node node) {
final PathAttributes attributes = new PathAttributes();
if(node.getReferenceId() != null) {
attributes.setFileId(String.valueOf(node.getReferenceId()));
}
attributes.setVersionId(String.valueOf(node.getId()));
attributes.setRevision(node.getBranchVersion());
if(node.isIsEncrypted() != null && !node.isIsEncrypted()) {
Expand Down Expand Up @@ -109,6 112,9 @@ public PathAttributes toAttributes(final Node node) {
public PathAttributes toAttributes(final DeletedNode node) {
final PathAttributes attributes = new PathAttributes();
attributes.setDuplicate(true);
if(node.getReferenceId() != null) {
attributes.setVersionId(String.valueOf(node.getReferenceId()));
}
attributes.setVersionId(String.valueOf(node.getId()));
attributes.setCreationDate(node.getCreatedAt() != null ? node.getCreatedAt().getMillis() : -1L);
attributes.setModificationDate(node.getUpdatedAt() != null ? node.getUpdatedAt().getMillis() : -1L);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 61,7 @@ public void delete(final Map<Path, TransferStatus> files, final PasswordCallback
set.put(file.getParent(), nodes);
}
callback.delete(file);
nodeid.cache(file, null);
nodeid.cache(file, null, null);
}
for(List<Long> nodes : regular.values()) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 65,9 @@ public Path copy(final Path source, final Path target, final TransferStatus stat
Long.parseLong(nodeid.getVersionId(target.getParent())),
StringUtils.EMPTY, null);
listener.sent(status.getLength());
nodeid.cache(target, null);
nodeid.cache(target, null, null);
final PathAttributes attributes = new SDSAttributesFinderFeature(session, nodeid).find(target);
nodeid.cache(target, attributes.getVersionId());
nodeid.cache(target, attributes.getVersionId(), attributes.getFileId());
return target.withAttributes(attributes);
}
catch(ApiException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 52,7 @@ public Path copy(final Path source, final Path target, final TransferStatus stat
status.setFilekey(SDSTripleCryptEncryptorFeature.generateFileKey());
}
final Path result = copy.copy(source, target, status, callback, listener);
nodeid.cache(target, null);
nodeid.cache(target, null, null);
return result.withAttributes(new SDSAttributesFinderFeature(session, nodeid).find(result));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 65,7 @@ else if(file.attributes().getVerdict() == PathAttributes.Verdict.malicious) {
new NodesApi(session.getClient()).removeNode(
Long.parseLong(nodeid.getVersionId(file)), StringUtils.EMPTY);
}
nodeid.cache(file, null);
nodeid.cache(file, null, null);
}
catch(ApiException e) {
throw new SDSExceptionMappingService(nodeid).map("Cannot delete {0}", e, file);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 74,7 @@ private Path createFolder(final Path folder) throws BackgroundException, ApiExce
folderRequest.setParentId(Long.parseLong(nodeid.getVersionId(folder.getParent())));
folderRequest.setName(folder.getName());
final Node node = new NodesApi(session.getClient()).createFolder(folderRequest, StringUtils.EMPTY, null);
nodeid.cache(folder, String.valueOf(node.getId()));
nodeid.cache(folder, String.valueOf(node.getId()), String.valueOf(node.getReferenceId()));
return folder.withAttributes(new SDSAttributesAdapter(session).toAttributes(node));
}

Expand All @@ -89,7 89,7 @@ protected Path createRoom(final Path room, final boolean encrypt) throws Backgro
}
roomRequest.setName(room.getName());
final Node node = new NodesApi(session.getClient()).createRoom(roomRequest, StringUtils.EMPTY, null);
nodeid.cache(room, String.valueOf(node.getId()));
nodeid.cache(room, String.valueOf(node.getId()), String.valueOf(node.getReferenceId()));
if(encrypt) {
final EncryptRoomRequest options = new EncryptRoomRequest();
options.setIsEncrypted(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 71,7 @@ public BackgroundException map(final String message, final ApiException failure,
// "debugInfo":"File not found","errorCode":-40751
case -40751:
// Invalidate cache on Node not found
fileid.cache(file, null);
fileid.cache(file, null, null);
break;
}
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 64,7 @@ protected AttributedList<Path> list(final Path directory, final ListProgressList
final PathAttributes attributes = feature.toAttributes(node);
final EnumSet<Path.Type> type = feature.toType(node);
final Path file = new Path(directory, node.getName(), type, attributes);
nodeid.cache(file, String.valueOf(node.getId()));
nodeid.cache(file, String.valueOf(node.getId()), String.valueOf(node.getReferenceId()));
children.add(file);
}
offset = chunksize;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 68,8 @@ public Path move(final Path file, final Path renamed, final TransferStatus statu
if(containerService.isContainer(file)) {
final Node node = new NodesApi(session.getClient()).updateRoom(
new UpdateRoomRequest().name(renamed.getName()), nodeId, StringUtils.EMPTY, null);
nodeid.cache(renamed, file.attributes().getVersionId());
nodeid.cache(file, null);
nodeid.cache(renamed, file.attributes().getVersionId(), file.attributes().getFileId());
nodeid.cache(file, null, null);
return renamed.withAttributes(new SDSAttributesAdapter(session).toAttributes(node));
}
else {
Expand Down Expand Up @@ -99,8 99,8 @@ public Path move(final Path file, final Path renamed, final TransferStatus statu
Long.parseLong(nodeid.getVersionId(renamed.getParent())),
StringUtils.EMPTY, null);
}
nodeid.cache(renamed, file.attributes().getVersionId());
nodeid.cache(file, null);
nodeid.cache(renamed, file.attributes().getVersionId(), file.attributes().getFileId());
nodeid.cache(file, null, null);
// Copy original file attributes
return renamed.withAttributes(new PathAttributes(file.attributes()).withVersionId(String.valueOf(nodeId)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 15,13 @@
* GNU General Public License for more details.
*/

import ch.cyberduck.core.CachingFileIdProvider;
import ch.cyberduck.core.CachingVersionIdProvider;
import ch.cyberduck.core.Path;
import ch.cyberduck.core.URIEncoder;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.exception.NotfoundException;
import ch.cyberduck.core.features.FileIdProvider;
import ch.cyberduck.core.features.VersionIdProvider;
import ch.cyberduck.core.preferences.HostPreferences;
import ch.cyberduck.core.sds.io.swagger.client.ApiException;
Expand All @@ -33,17 35,31 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class SDSNodeIdProvider extends CachingVersionIdProvider implements VersionIdProvider {
public class SDSNodeIdProvider implements FileIdProvider, VersionIdProvider {
private static final Logger log = LogManager.getLogger(SDSNodeIdProvider.class);

private static final UnicodeNormalizer normalizer = new NFCNormalizer();
private static final String ROOT_NODE_ID = "0";

private final SDSSession session;
/**
* Node id as file version
*/
private final CachingVersionIdProvider versions;
/**
* Reference id that is static across different file versions
*/
private final CachingFileIdProvider references;

public SDSNodeIdProvider(final SDSSession session) {
super(session.getCaseSensitivity());
this.session = session;
this.versions = new CachingVersionIdProvider(session.getCaseSensitivity());
this.references = new CachingFileIdProvider(session.getCaseSensitivity());
}

public void cache(final Path file, final String nodeId, final String referenceId) {
this.versions.cache(file, nodeId);
this.references.cache(file, referenceId);
}

@Override
Expand All @@ -54,20 70,61 @@ public String getVersionId(final Path file) throws BackgroundException {
}
return file.attributes().getVersionId();
}
final String cached = super.getVersionId(file);
final String cached = versions.getVersionId(file);
if(cached != null) {
if(log.isDebugEnabled()) {
log.debug(String.format("Return cached versionid %s for file %s", cached, file));
}
return cached;
}
return this.getNodeId(file, new HostPreferences(session.getHost()).getInteger("sds.listing.chunksize"));
final Node node = this.getNode(file, new HostPreferences(session.getHost()).getInteger("sds.listing.chunksize"));
if(null == node) {
return ROOT_NODE_ID;
}
if(null != node.getId()) {
return String.valueOf(node.getId());
}
return null;
}

protected String getNodeId(final Path file, final int chunksize) throws BackgroundException {
if(file.isRoot()) {
@Override
public String getFileId(final Path file) throws BackgroundException {
if(file.isDirectory()) {
return null;
}
if(StringUtils.isNotBlank(file.attributes().getFileId())) {
if(log.isDebugEnabled()) {
log.debug(String.format("Return version %s from attributes for file %s", file.attributes().getFileId(), file));
}
return file.attributes().getFileId();
}
final String cached = references.getFileId(file);
if(cached != null) {
if(log.isDebugEnabled()) {
log.debug(String.format("Return cached versionid %s for file %s", cached, file));
}
return cached;
}
final Node node = this.getNode(file, new HostPreferences(session.getHost()).getInteger("sds.listing.chunksize"));
if(null == node) {
return ROOT_NODE_ID;
}
if(null != node.getReferenceId()) {
return String.valueOf(node.getReferenceId());
}
return null;
}

@Override
public void clear() {
versions.clear();
references.clear();
}

protected Node getNode(final Path file, final int chunksize) throws BackgroundException {
if(file.isRoot()) {
return null;
}
try {
final String type;
if(file.isDirectory()) {
Expand Down Expand Up @@ -101,7 158,13 @@ protected String getNodeId(final Path file, final int chunksize) throws Backgrou
if(log.isInfoEnabled()) {
log.info(String.format("Return node %s for file %s", node.getId(), file));
}
return this.cache(file, node.getId().toString());
if(node.getId() != null) {
versions.cache(file, node.getId().toString());
}
if(node.getReferenceId() != null) {
references.cache(file, node.getReferenceId().toString());
}
return node;
}
}
offset = chunksize;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 84,7 @@ public InputStream read(final Path file, final TransferStatus status, final Conn
case HttpStatus.SC_PARTIAL_CONTENT:
return new HttpMethodReleaseInputStream(response, status);
case HttpStatus.SC_NOT_FOUND:
nodeid.cache(file, null);
nodeid.cache(file, null, null);
// Break through
default:
throw new DefaultHttpResponseExceptionMappingService().map("Download {0} failed", new HttpResponseException(
Expand Down
3 changes: 3 additions & 0 deletions dracoon/src/main/java/ch/cyberduck/core/sds/SDSSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 569,9 @@ public <T> T _getFeature(final Class<T> type) {
if(type == Delete.class) {
return (T) new SDSThresholdDeleteFeature(this, nodeid);
}
if(type == SDSNodeIdProvider.class) {
return (T) nodeid;
}
if(type == VersionIdProvider.class) {
return (T) nodeid;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 171,7 @@ public Node complete(final Path file, final String uploadToken, final TransferSt
}
}
}
nodeid.cache(file, String.valueOf(upload.getId()));
nodeid.cache(file, String.valueOf(upload.getId()), String.valueOf(upload.getReferenceId()));
return upload;
}
catch(ApiException e) {
Expand Down Expand Up @@ -260,7 260,7 @@ public void uncaughtException(final Thread t, final Throwable e) {
break;
case "done":
// Set node id in transfer status
nodeid.cache(file, String.valueOf(uploadStatus.getNode().getId()));
nodeid.cache(file, String.valueOf(uploadStatus.getNode().getId()), String.valueOf(uploadStatus.getNode().getReferenceId()));
// Mark parent status as complete
status.withResponse(new SDSAttributesAdapter(session).toAttributes(uploadStatus.getNode())).setComplete();
signal.countDown();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 179,7 @@ public void testChangedNodeId() throws Exception {
// Assume previously seen but changed on server
final String invalidId = String.valueOf(RandomUtils.nextLong());
test.attributes().setVersionId(invalidId);
nodeid.cache(test, invalidId);
nodeid.cache(test, invalidId, null);
final SDSAttributesFinderFeature f = new SDSAttributesFinderFeature(session, nodeid);
assertEquals(latestnodeid, f.find(test).getVersionId());
assertEquals(latestnodeid, test.attributes().getVersionId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 91,7 @@ public void testWrite() throws Exception {
new StreamCopier(status, status).transfer(new ByteArrayInputStream(content), out);
assertEquals(content.length, out.getStatus().getSize(), 0L);
}
assertNotNull(test.attributes().getFileId());
assertNotNull(test.attributes().getVersionId());
assertTrue(new DefaultFindFeature(session).find(test));
assertTrue(new SDSFindFeature(session, nodeid).find(test));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 179,7 @@ public void testWriteParentRoomReplaced() throws Exception {
final String rommname = new AlphanumericRandomStringService().random();
final Path room = new SDSDirectoryFeature(session, nodeid).mkdir(
new Path(rommname, EnumSet.of(Path.Type.directory, Path.Type.volume)), new TransferStatus());
final String fileid = nodeid.getNodeId(room, 1);
final String fileid = String.valueOf(nodeid.getNode(room, 1).getId());
assertEquals(fileid, room.attributes().getVersionId());
final Path test = new Path(room, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file));
new SDSDeleteFeature(session, nodeid).delete(Collections.singletonList(room), new DisabledLoginCallback(), new Delete.DisabledCallback());
Expand Down
Loading
Loading