116 lines
3.5 KiB
Java
116 lines
3.5 KiB
Java
package org.warp.jcwdb;
|
|
|
|
import java.io.IOException;
|
|
import java.lang.ref.WeakReference;
|
|
import java.nio.channels.ClosedChannelException;
|
|
|
|
import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry;
|
|
|
|
public class Cleaner {
|
|
|
|
private static final double MAXIMUM_SLEEP_INTERVAL = 20d * 1000d; // 20 minutes
|
|
private static final double MINIMUM_SLEEP_INTERVAL = 1d * 1000d; // 1 second
|
|
private static final double NORMAL_REMOVED_ITEMS = 1000l;
|
|
private static final double REMOVED_ITEMS_RATIO = 2.5d; // 250%
|
|
|
|
private final Cleanable[] objectsToClean;
|
|
private final Thread cleanerThread;
|
|
private int sleepInterval = (int) MINIMUM_SLEEP_INTERVAL;
|
|
private volatile boolean stopRequest = false;
|
|
|
|
public Cleaner(Cleanable... objectsToClean) {
|
|
this.objectsToClean = objectsToClean;
|
|
this.cleanerThread = new Thread(new CleanLoop());
|
|
this.cleanerThread.setName("Cleaner thread");
|
|
this.cleanerThread.setDaemon(true);
|
|
}
|
|
|
|
public void start() {
|
|
this.cleanerThread.start();
|
|
}
|
|
|
|
/**
|
|
* Clean
|
|
* @return number of removed items
|
|
*/
|
|
private long clean() {
|
|
long cleanedItems = 0;
|
|
for (Cleanable cleanable : objectsToClean) {
|
|
cleanedItems += cleanable.clean();
|
|
}
|
|
System.gc();
|
|
return cleanedItems;
|
|
}
|
|
|
|
public void stop() {
|
|
if (cleanerThread != null) {
|
|
stopRequest = true;
|
|
while (cleanerThread.isAlive()) {
|
|
try {
|
|
Thread.sleep(100);
|
|
} catch (InterruptedException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private class CleanLoop implements Runnable {
|
|
|
|
@Override
|
|
public void run() {
|
|
while(!stopRequest) {
|
|
try {
|
|
System.out.println("[CLEANER] Waiting " + sleepInterval + "ms.");
|
|
sleepFor(sleepInterval);
|
|
final double removedItems = clean();
|
|
double suggestedExecutionTimeByItemsCalculations = (sleepInterval + MAXIMUM_SLEEP_INTERVAL) / 2;
|
|
|
|
System.out.println("[CLEANER] REMOVED_ITEMS: " + removedItems);
|
|
if (removedItems > 0) {
|
|
final double removedItemsRatio = removedItems / NORMAL_REMOVED_ITEMS;
|
|
System.out.println("[CLEANER] REMOVED_ITEMS_RATIO: " + removedItemsRatio);
|
|
if (removedItemsRatio < 1d / REMOVED_ITEMS_RATIO && removedItemsRatio >= REMOVED_ITEMS_RATIO) {
|
|
suggestedExecutionTimeByItemsCalculations = sleepInterval / removedItemsRatio;
|
|
}
|
|
}
|
|
|
|
System.out.println("[CLEANER] Items: SUGGESTING SLEEP_INTERVAL FROM " + sleepInterval + "ms TO " + suggestedExecutionTimeByItemsCalculations + "ms");
|
|
|
|
double newSleepInterval = suggestedExecutionTimeByItemsCalculations;
|
|
System.out.println("[CLEANER] Total: SUGGESTING SLEEP_INTERVAL FROM " + sleepInterval + "ms TO " + newSleepInterval + "ms");
|
|
if (newSleepInterval > MAXIMUM_SLEEP_INTERVAL) {
|
|
sleepInterval = (int) MAXIMUM_SLEEP_INTERVAL;
|
|
} else if (newSleepInterval < MINIMUM_SLEEP_INTERVAL) {
|
|
sleepInterval = (int) MINIMUM_SLEEP_INTERVAL;
|
|
} else {
|
|
System.out.println("[CLEANER] CHANGED SLEEP_INTERVAL FROM " + sleepInterval + "ms TO " + newSleepInterval + "ms");
|
|
sleepInterval = (int) newSleepInterval;
|
|
}
|
|
|
|
|
|
System.out.println("[CLEANER] Cleaned " + removedItems + " items.");
|
|
}catch (InterruptedException e) {
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
private void sleepFor(int sleepInterval) throws InterruptedException {
|
|
int lastI = (int) Math.ceil(((double) sleepInterval) / 1000d);
|
|
for (int i = 0; i < lastI; i++) {
|
|
if (stopRequest) {
|
|
return;
|
|
}
|
|
if (i == lastI) {
|
|
Thread.sleep(sleepInterval % 1000);
|
|
} else {
|
|
Thread.sleep(lastI);
|
|
}
|
|
Thread.sleep(sleepInterval);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|