package com.hubspot.blazar.data.cache;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.inject.Inject;
import javax.inject.Singleton;
import com.hubspot.blazar.base.RepositoryState;
import com.hubspot.blazar.data.service.StateService;
@Singleton
public class StateCache {
private final StateService stateService;
private final Map<Integer, RepositoryState> cache;
private final AtomicLong cacheTimestamp;
private final ReadWriteLock lock;
@Inject
public StateCache(StateService stateService) {
this.stateService = stateService;
this.cache = new ConcurrentHashMap<>();
long maxTime = 0;
for (RepositoryState state : stateService.getAllRepositoryStates()) {
cache.put(state.getGitInfo().getId().get(), state);
if (state.getGitInfo().getUpdatedTimestamp() > maxTime) {
maxTime = state.getGitInfo().getUpdatedTimestamp();
}
}
this.cacheTimestamp = new AtomicLong(maxTime);
this.lock = new ReentrantReadWriteLock();
}
public Set<RepositoryState> getAllRepositoryStates() {
updateCache();
Lock readLock = lock.readLock();
readLock.lock();
try {
return new HashSet<>(cache.values());
} finally {
readLock.unlock();
}
}
private void updateCache() {
Lock writeLock = lock.writeLock();
if (writeLock.tryLock()) {
try {
Set<RepositoryState> changes = stateService.getChangedRepositoryStates(cacheTimestamp.get());
long maxTime = cacheTimestamp.get();
for (RepositoryState change : changes) {
int branchId = change.getGitInfo().getId().get();
if (change.getGitInfo().isActive()) {
cache.put(branchId, change);
} else {
cache.remove(branchId);
}
if (change.getGitInfo().getUpdatedTimestamp() > maxTime) {
maxTime = change.getGitInfo().getUpdatedTimestamp();
}
}
cacheTimestamp.set(maxTime);
} finally {
writeLock.unlock();
}
}
}
}