Synchronize auto queries

This commit is contained in:
Alexander Söderberg 2020-08-17 01:27:45 +02:00
parent 87f0b1fc97
commit 351ae1b2c7
No known key found for this signature in database
GPG Key ID: C0207FF7EA146678

View File

@ -1,5 +1,7 @@
package com.plotsquared.core.services.plots; package com.plotsquared.core.services.plots;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.intellectualsites.services.types.Service; import com.intellectualsites.services.types.Service;
import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
@ -11,10 +13,15 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate; import java.util.function.Predicate;
public interface AutoService extends Service<AutoService.AutoQuery, List<Plot>> { public interface AutoService extends Service<AutoService.AutoQuery, List<Plot>> {
Cache<PlotId, Plot> plotCandidateCache = CacheBuilder.newBuilder()
.expireAfterWrite(20, TimeUnit.SECONDS).build();
Object plotLock = new Object();
final class AutoQuery { final class AutoQuery {
private final PlotPlayer<?> player; private final PlotPlayer<?> player;
@ -101,11 +108,17 @@ public interface AutoService extends Service<AutoService.AutoQuery, List<Plot>>
final class SinglePlotService implements AutoService, Predicate<AutoQuery> { final class SinglePlotService implements AutoService, Predicate<AutoQuery> {
@Nullable @Override public List<Plot> handle(@Nonnull AutoQuery autoQuery) { @Nullable @Override public List<Plot> handle(@Nonnull AutoQuery autoQuery) {
final Plot plot = autoQuery.getPlotArea().getNextFreePlot(autoQuery.getPlayer(), autoQuery.getStartId()); Plot plot;
if (plot == null) { do {
return null; synchronized (plotLock) {
} plot = autoQuery.getPlotArea().getNextFreePlot(autoQuery.getPlayer(), autoQuery.getStartId());
return Collections.singletonList(plot); if (plot != null && plotCandidateCache.getIfPresent(plot.getId()) == null) {
plotCandidateCache.put(plot.getId(), plot);
return Collections.singletonList(plot);
}
}
} while (plot != null);
return null;
} }
@Override public boolean test(@Nonnull final AutoQuery autoQuery) { @Override public boolean test(@Nonnull final AutoQuery autoQuery) {
@ -119,13 +132,24 @@ public interface AutoService extends Service<AutoService.AutoQuery, List<Plot>>
@Override public List<Plot> handle(@Nonnull final AutoQuery autoQuery) { @Override public List<Plot> handle(@Nonnull final AutoQuery autoQuery) {
/* TODO: Add timeout? */ /* TODO: Add timeout? */
while (true) { outer: while (true) {
final PlotId start = autoQuery.getPlotArea().getMeta("lastPlot", PlotId.of(0, 0)).getNextId(); synchronized (plotLock) {
final PlotId end = PlotId.of(start.getX() + autoQuery.getSizeX() - 1, start.getY() + autoQuery.getSizeZ() - 1); final PlotId start =
final List<Plot> plots = autoQuery.getPlotArea().canClaim(autoQuery.getPlayer(), start, end); autoQuery.getPlotArea().getMeta("lastPlot", PlotId.of(0, 0)).getNextId();
if (plots != null && !plots.isEmpty()) { final PlotId end = PlotId.of(start.getX() + autoQuery.getSizeX() - 1,
autoQuery.getPlotArea().setMeta("lastPlot", start); start.getY() + autoQuery.getSizeZ() - 1);
return plots; final List<Plot> plots =
autoQuery.getPlotArea().canClaim(autoQuery.getPlayer(), start, end);
if (plots != null && !plots.isEmpty()) {
autoQuery.getPlotArea().setMeta("lastPlot", start);
for (final Plot plot : plots) {
if (plotCandidateCache.getIfPresent(plot.getId()) != null) {
continue outer;
}
plotCandidateCache.put(plot.getId(), plot);
}
return plots;
}
} }
} }
} }