mirror of https://github.com/webbukkit/dynmap.git
122 lines
4.0 KiB
Java
122 lines
4.0 KiB
Java
package org.dynmap;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
|
|
public class UpdateQueue {
|
|
public Object lock = new Object();
|
|
private HashMap<UpdateRec,UpdateRec> updateSet = new HashMap<UpdateRec,UpdateRec>();
|
|
private UpdateRec orderedlist = null; /* Oldest to youngest */
|
|
private static final long maxUpdateAge = 120000;
|
|
private static final long ageOutPeriod = 5000;
|
|
private long lastageout = 0;
|
|
|
|
private static class UpdateRec {
|
|
Client.Update u;
|
|
UpdateRec next;
|
|
UpdateRec prev;
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if(o instanceof UpdateRec)
|
|
return u.equals(((UpdateRec)o).u);
|
|
return false;
|
|
}
|
|
@Override
|
|
public int hashCode() {
|
|
return u.hashCode();
|
|
}
|
|
}
|
|
|
|
private void doAgeOut(long now) {
|
|
/* If we're due */
|
|
if((now < lastageout) || (now > (lastageout + ageOutPeriod))) {
|
|
lastageout = now;
|
|
long deadline = now - maxUpdateAge;
|
|
while((orderedlist != null) && (orderedlist.u.timestamp < deadline)) {
|
|
UpdateRec r = orderedlist;
|
|
|
|
updateSet.remove(r); /* Remove record from set */
|
|
if(r.next == r) {
|
|
orderedlist = null;
|
|
}
|
|
else {
|
|
orderedlist = r.next;
|
|
r.next.prev = r.prev;
|
|
r.prev.next = r.next;
|
|
}
|
|
r.next = r.prev = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void pushUpdate(Client.Update obj) {
|
|
synchronized (lock) {
|
|
/* Do inside lock - prevent delay between time and actual work */
|
|
long now = System.currentTimeMillis();
|
|
doAgeOut(now); /* Consider age out */
|
|
UpdateRec r = new UpdateRec();
|
|
r.u = obj;
|
|
r.u.timestamp = now; // Use our timestamp: makes sure order is preserved
|
|
UpdateRec oldr = updateSet.remove(r); /* Try to remove redundant event */
|
|
if(oldr != null) { /* If found, remove from ordered list too */
|
|
if(oldr.next == oldr) { /* Only one? */
|
|
orderedlist = null;
|
|
}
|
|
else {
|
|
if(orderedlist == oldr) { /* We're oldest? */
|
|
orderedlist = oldr.next;
|
|
}
|
|
oldr.next.prev = oldr.prev;
|
|
oldr.prev.next = oldr.next;
|
|
}
|
|
oldr.next = oldr.prev = null;
|
|
}
|
|
updateSet.put(r, r);
|
|
/* Add to end of ordered list */
|
|
if(orderedlist == null) {
|
|
orderedlist = r;
|
|
r.next = r.prev = r;
|
|
}
|
|
else {
|
|
r.next = orderedlist;
|
|
r.prev = orderedlist.prev;
|
|
r.next.prev = r.prev.next = r;
|
|
}
|
|
}
|
|
}
|
|
|
|
private ArrayList<Client.Update> tmpupdates = new ArrayList<Client.Update>();
|
|
|
|
public Client.Update[] getUpdatedObjects(long since) {
|
|
Client.Update[] updates;
|
|
synchronized (lock) {
|
|
long now = System.currentTimeMillis();
|
|
doAgeOut(now); /* Consider age out */
|
|
|
|
tmpupdates.clear();
|
|
if(orderedlist != null) {
|
|
UpdateRec r = orderedlist.prev; /* Get newest */
|
|
while(r != null) {
|
|
if(r.u.timestamp >= since) {
|
|
tmpupdates.add(r.u);
|
|
if(r == orderedlist)
|
|
r = null;
|
|
else
|
|
r = r.prev;
|
|
}
|
|
else {
|
|
r = null;
|
|
}
|
|
}
|
|
}
|
|
// Reverse output.
|
|
updates = new Client.Update[tmpupdates.size()];
|
|
for (int i = 0; i < updates.length; i++) {
|
|
updates[i] = tmpupdates.get(updates.length-1-i);
|
|
}
|
|
}
|
|
return updates;
|
|
}
|
|
}
|