Added org.simantics.filesystem.services
[simantics/platform.git] / bundles / org.simantics.filesystem.services / src / org / simantics / filesystem / services / internal / sizetracker / SizeTrackerImpl.java
1 package org.simantics.filesystem.services.internal.sizetracker;
2
3 import java.io.IOException;
4 import java.nio.file.Path;
5 import java.util.concurrent.CopyOnWriteArrayList;
6 import java.util.function.Consumer;
7 import java.util.function.LongConsumer;
8
9 import org.simantics.filesystem.services.sizetracker.SizeChangeEvent;
10 import org.simantics.filesystem.services.sizetracker.SizeTracker;
11 import org.simantics.utils.datastructures.file.DirectorySizeTracker;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14
15 /**
16  * @author Tuukka Lehtonen
17  * @since 1.31.0
18  * 
19  * TODO: change to use quiet time and "post notification" to throttle updates
20  */
21 public class SizeTrackerImpl implements SizeTracker {
22
23         private Logger logger = LoggerFactory.getLogger(SizeTrackerImpl.class);
24
25         private Path path;
26         private DirectorySizeServiceImpl service;
27         private DirectorySizeTracker tracker;
28         private CopyOnWriteArrayList<Consumer<SizeChangeEvent>> listeners = new CopyOnWriteArrayList<>();
29         private volatile long oldSize = 0L;
30
31         private LongConsumer theListener = newSize -> {
32                 long os = oldSize;
33                 oldSize = newSize;
34                 //logger.info(path + ": size changed: " + ((double) os / (1024.0*1024.0)) + " MB -> " + ((double) newSize / (1024.0*1024.0)) + " MB");
35                 fireSizeChange(os, newSize);
36         };
37
38         public SizeTrackerImpl(DirectorySizeServiceImpl service, Path path) throws IOException {
39                 this.service = service;
40                 this.path = path;
41                 this.tracker = DirectorySizeTracker.startTracker(theListener);
42         }
43
44         public SizeTrackerImpl start() throws IOException {
45                 new Thread(() -> {
46                         try {
47                                 synchronized (SizeTrackerImpl.this) {
48                                         if (tracker != null)
49                                                 tracker.track(path);
50                                 }
51                         } catch (IOException e) {
52                                 logger.error("Failed to start tracking size of directory " + path, e);
53                         }
54                 }, "SizeTrackerStarter").start();
55                 return this;
56         }
57
58         @Override
59         public synchronized void close() throws IOException {
60                 if (tracker == null)
61                         return;
62                 tracker.close();
63                 tracker = null;
64                 service.removeTracker(path);
65         }
66
67         @Override
68         public Path path() {
69                 return path;
70         }
71
72         @Override
73         public long size() {
74                 return oldSize;
75         }
76
77         @Override
78         public void addListener(Consumer<SizeChangeEvent> listener) {
79                 listeners.add(listener);
80         }
81
82         @Override
83         public void removeListener(Consumer<SizeChangeEvent> listener) {
84                 listeners.remove(listener);
85         }
86
87         private void fireSizeChange(long oldSize, long newSize) {
88                 SizeChangeEvent e = new SizeChangeEventImpl(path, oldSize, newSize);
89                 listeners.forEach(c -> c.accept(e));
90         }
91
92 }