Skip to content

Commit

Permalink
Refactor to add single execution to scheduler interface.
Browse files Browse the repository at this point in the history
  • Loading branch information
dkocher committed Nov 26, 2024
1 parent 917433a commit ebe9333
Show file tree
Hide file tree
Showing 18 changed files with 163 additions and 209 deletions.
17 changes: 14 additions & 3 deletions core/src/main/java/ch/cyberduck/core/features/Scheduler.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,23 @@
*/

import ch.cyberduck.core.PasswordCallback;
import ch.cyberduck.core.pool.SessionPool;

import java.util.concurrent.Future;

@Optional
public interface Scheduler<R> {
R repeat(SessionPool pool, PasswordCallback callback);
/**
* Repeated execution on background thread
*/
Future<R> repeat(PasswordCallback callback);

void shutdown();
/**
* Single execution on background thread with no delay
*/
Future<R> execute(PasswordCallback callback);

/**
* Shutdown thread pool
*/
void shutdown();
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

import ch.cyberduck.core.PasswordCallback;
import ch.cyberduck.core.features.Scheduler;
import ch.cyberduck.core.pool.SessionPool;

import java.util.concurrent.Future;

public class DelegatingSchedulerFeature implements Scheduler<Void> {

Expand All @@ -28,9 +29,17 @@ public DelegatingSchedulerFeature(final Scheduler... features) {
}

@Override
public Void repeat(final SessionPool pool, final PasswordCallback callback) {
public Future<Void> repeat(final PasswordCallback callback) {
for(Scheduler scheduler : features) {
scheduler.repeat(callback);
}
return null;
}

@Override
public Future<Void> execute(final PasswordCallback callback) {
for(Scheduler scheduler : features) {
scheduler.repeat(pool, callback);
scheduler.execute(callback);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,18 @@
*/

import ch.cyberduck.core.PasswordCallback;
import ch.cyberduck.core.Path;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.features.Scheduler;
import ch.cyberduck.core.pool.SessionPool;
import ch.cyberduck.core.threading.ThreadPool;
import ch.cyberduck.core.threading.ThreadPoolFactory;

import java.util.concurrent.Callable;
import java.util.concurrent.Future;

public abstract class OneTimeSchedulerFeature<R> implements Scheduler<Future<R>> {
public abstract class OneTimeSchedulerFeature<R> extends ThreadPoolSchedulerFeature<R> {

private final Path file;

private final ThreadPool scheduler = ThreadPoolFactory.get("scheduler", 1);

public OneTimeSchedulerFeature(final Path file) {
this.file = file;
}

protected abstract R operate(PasswordCallback callback, Path file) throws BackgroundException;

@Override
public Future<R> repeat(final SessionPool pool, final PasswordCallback callback) {
return scheduler.execute(new Callable<R>() {
@Override
public R call() throws Exception {
return operate(callback, file);
}
});
public OneTimeSchedulerFeature() {
super(Long.MAX_VALUE);
}

@Override
public void shutdown() {
scheduler.shutdown(false);
public Future<R> repeat(final PasswordCallback callback) {
// No repeat
return this.execute(callback);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package ch.cyberduck.core.shared;

/*
* Copyright (c) 2002-2017 iterate GmbH. All rights reserved.
* https://cyberduck.io/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

import ch.cyberduck.core.PasswordCallback;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.features.Scheduler;
import ch.cyberduck.core.threading.ScheduledThreadPool;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public abstract class ThreadPoolSchedulerFeature<R> implements Scheduler<R> {
private static final Logger log = LogManager.getLogger(ThreadPoolSchedulerFeature.class);

private final long period;
private final ScheduledThreadPool scheduler = new ScheduledThreadPool();

public ThreadPoolSchedulerFeature(final long period) {
this.period = period;
}

@Override
public Future<R> repeat(final PasswordCallback callback) {
return (ScheduledFuture<R>) scheduler.repeat(new FailureAwareRunnable(callback), period, TimeUnit.MILLISECONDS);
}

@Override
public Future<R> execute(final PasswordCallback callback) {
return (ScheduledFuture<R>) scheduler.schedule(new FailureAwareRunnable(callback), 0L, TimeUnit.MILLISECONDS);
}

protected abstract R operate(PasswordCallback callback) throws BackgroundException;

@Override
public void shutdown() {
log.debug("Shutting down scheduler thread pool");
scheduler.shutdown();
}

private final class FailureAwareRunnable implements Runnable {
private final PasswordCallback callback;

public FailureAwareRunnable(final PasswordCallback callback) {
this.callback = callback;
}

@Override
public void run() {
try {
ThreadPoolSchedulerFeature.this.operate(callback);
}
catch(BackgroundException e) {
log.warn("Failure processing scheduled task. {}", e.getMessage(), e);
}
catch(Exception e) {
log.error("Failure processing scheduled task {}", e.getMessage(), e);
ThreadPoolSchedulerFeature.this.shutdown();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.features.Bulk;
import ch.cyberduck.core.features.Delete;
import ch.cyberduck.core.features.Scheduler;
import ch.cyberduck.core.preferences.HostPreferences;
import ch.cyberduck.core.transfer.Transfer;
import ch.cyberduck.core.transfer.TransferItem;
Expand Down Expand Up @@ -91,15 +92,15 @@ public void post(final Transfer.Type type, final Map<TransferItem, TransferStatu
default:
if(new HostPreferences(session.getHost()).getBoolean("sds.encryption.missingkeys.upload")) {
if(session.userAccount().isEncryptionEnabled()) {
final SDSMissingFileKeysSchedulerFeature background = new SDSMissingFileKeysSchedulerFeature();
final Scheduler scheduler = session.getFeature(Scheduler.class);
final Map<Path, Boolean> rooms = this.getRoomEncryptionStatus(files);
for(Map.Entry<TransferItem, TransferStatus> entry : files.entrySet()) {
final Path file = entry.getKey().remote;
if(file.isFile()) {
final Path container = containerService.getContainer(file);
if(rooms.get(container)) {
log.debug("Run missing file keys for {}", file);
background.single(session, callback, file);
scheduler.execute(callback);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@
import ch.cyberduck.core.Credentials;
import ch.cyberduck.core.PasswordCallback;
import ch.cyberduck.core.Path;
import ch.cyberduck.core.Session;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.features.VersionIdProvider;
import ch.cyberduck.core.preferences.HostPreferences;
import ch.cyberduck.core.preferences.PreferencesFactory;
import ch.cyberduck.core.sds.io.swagger.client.ApiException;
Expand All @@ -36,7 +34,7 @@
import ch.cyberduck.core.sds.triplecrypt.TripleCryptConverter;
import ch.cyberduck.core.sds.triplecrypt.TripleCryptExceptionMappingService;
import ch.cyberduck.core.sds.triplecrypt.TripleCryptKeyPair;
import ch.cyberduck.core.shared.AbstractSchedulerFeature;
import ch.cyberduck.core.shared.ThreadPoolSchedulerFeature;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
Expand All @@ -61,21 +59,30 @@

import static java.util.stream.Collectors.groupingBy;

public class SDSMissingFileKeysSchedulerFeature extends AbstractSchedulerFeature<List<UserFileKeySetRequest>> {
public class SDSMissingFileKeysSchedulerFeature extends ThreadPoolSchedulerFeature<List<UserFileKeySetRequest>> {
private static final Logger log = LogManager.getLogger(SDSMissingFileKeysSchedulerFeature.class);

public SDSMissingFileKeysSchedulerFeature() {
this(PreferencesFactory.get().getLong("sds.encryption.missingkeys.scheduler.period"));
private final SDSSession session;
private final SDSNodeIdProvider nodeid;
private final Path file;

public SDSMissingFileKeysSchedulerFeature(final SDSSession session, final SDSNodeIdProvider nodeid) {
this(session, nodeid, null);
}

public SDSMissingFileKeysSchedulerFeature(final SDSSession session, final SDSNodeIdProvider nodeid, final Path file) {
this(session, nodeid, file, PreferencesFactory.get().getLong("sds.encryption.missingkeys.scheduler.period"));
}

public SDSMissingFileKeysSchedulerFeature(final long period) {
public SDSMissingFileKeysSchedulerFeature(final SDSSession session, final SDSNodeIdProvider nodeid, final Path file, final long period) {
super(period);
this.file = file;
this.session = session;
this.nodeid = nodeid;
}

@Override
public List<UserFileKeySetRequest> operate(final Session<?> client, final PasswordCallback callback, final Path file) throws BackgroundException {
final SDSSession session = (SDSSession) client;
final SDSNodeIdProvider nodeid = (SDSNodeIdProvider) session._getFeature(VersionIdProvider.class);
protected List<UserFileKeySetRequest> operate(final PasswordCallback callback) throws BackgroundException {
try {
final UserAccountWrapper account = session.userAccount();
if(!account.isEncryptionEnabled()) {
Expand Down
Loading

0 comments on commit ebe9333

Please sign in to comment.