package org.simantics.filesystem.services.internal.sizetracker; import java.io.IOException; import java.nio.file.Path; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Consumer; import java.util.function.LongConsumer; import org.simantics.filesystem.services.sizetracker.SizeChangeEvent; import org.simantics.filesystem.services.sizetracker.SizeTracker; import org.simantics.utils.datastructures.file.DirectorySizeTracker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Tuukka Lehtonen * @since 1.31.0 * * TODO: change to use quiet time and "post notification" to throttle updates */ public class SizeTrackerImpl implements SizeTracker { private Logger logger = LoggerFactory.getLogger(SizeTrackerImpl.class); private Path path; private DirectorySizeServiceImpl service; private DirectorySizeTracker tracker; private CopyOnWriteArrayList> listeners = new CopyOnWriteArrayList<>(); private volatile long oldSize = 0L; private LongConsumer theListener = newSize -> { long os = oldSize; oldSize = newSize; //logger.info(path + ": size changed: " + ((double) os / (1024.0*1024.0)) + " MB -> " + ((double) newSize / (1024.0*1024.0)) + " MB"); fireSizeChange(os, newSize); }; public SizeTrackerImpl(DirectorySizeServiceImpl service, Path path) throws IOException { this.service = service; this.path = path; this.tracker = DirectorySizeTracker.startTracker(theListener); } public SizeTrackerImpl start() throws IOException { new Thread(() -> { try { synchronized (SizeTrackerImpl.this) { if (tracker != null) tracker.track(path); } } catch (IOException e) { logger.error("Failed to start tracking size of directory " + path, e); } }, "SizeTrackerStarter").start(); return this; } @Override public synchronized void close() throws IOException { if (tracker == null) return; tracker.close(); tracker = null; service.removeTracker(path); } @Override public Path path() { return path; } @Override public long size() { return oldSize; } @Override public void addListener(Consumer listener) { listeners.add(listener); } @Override public void removeListener(Consumer listener) { listeners.remove(listener); } private void fireSizeChange(long oldSize, long newSize) { SizeChangeEvent e = new SizeChangeEventImpl(path, oldSize, newSize); listeners.forEach(c -> c.accept(e)); } }