mirror of
https://github.com/CivMC/Civ.git
synced 2026-07-15 23:20:44 +00:00
Bug fix
Very minimal testing has been done, but Citadel is now no longer a steaming heap of bricks. Aside from fixing bugs, I've changed tabs to 4 spaces in both Citadel.java and my Dao extension.
This commit is contained in:
@@ -71,95 +71,95 @@ public class Citadel extends JavaPlugin {
|
||||
private static Citadel plugin;
|
||||
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args){
|
||||
return commandHandler.dispatch(sender, label, args);
|
||||
return commandHandler.dispatch(sender, label, args);
|
||||
}
|
||||
|
||||
public void onEnable() {
|
||||
plugin = this;
|
||||
configManager.load();
|
||||
dao = new CitadelCachingDao(this);
|
||||
dao.updateDatabase();
|
||||
setUpStorage();
|
||||
registerCommands();
|
||||
registerEvents();
|
||||
configManager.load();
|
||||
for(Player player : getServer().getOnlinePlayers()){
|
||||
memberManager.addOnlinePlayer(player);
|
||||
memberManager.addOnlinePlayer(player);
|
||||
}
|
||||
try {
|
||||
Metrics metrics = new Metrics(this);
|
||||
metrics.start();
|
||||
} catch (IOException e) {
|
||||
// Failed to submit the stats :-(
|
||||
System.out.println("failed");
|
||||
System.out.println("failed");
|
||||
}
|
||||
log.info("[Citadel] Citadel is now enabled.");
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
//There should be some interface that CitadelCachingDao can implement that does this automatically on disable:
|
||||
//There should be some interface that CitadelCachingDao can implement that does this automatically on disable:
|
||||
//I don't want to do this as close() or finalize() because I want to make sure the database connection is still alive.
|
||||
if( dao instanceof CitadelCachingDao ){
|
||||
if( dao instanceof CitadelCachingDao ){
|
||||
((CitadelCachingDao)dao).shutDown();
|
||||
}
|
||||
log.info("[Citadel] Citadel is now disabled.");
|
||||
}
|
||||
|
||||
public void setUpStorage(){
|
||||
GroupStorage groupStorage = new GroupStorage(dao);
|
||||
groupManager.setStorage(groupStorage);
|
||||
|
||||
PersonalGroupStorage personalGroupStorage = new PersonalGroupStorage(dao);
|
||||
personalGroupManager.setStorage(personalGroupStorage);
|
||||
|
||||
MemberStorage memberStorage = new MemberStorage(dao);
|
||||
memberManager.setStorage(memberStorage);
|
||||
|
||||
ReinforcementStorage reinforcementStorage = new ReinforcementStorage(dao);
|
||||
reinforcementManager.setStorage(reinforcementStorage);
|
||||
GroupStorage groupStorage = new GroupStorage(dao);
|
||||
groupManager.setStorage(groupStorage);
|
||||
|
||||
PersonalGroupStorage personalGroupStorage = new PersonalGroupStorage(dao);
|
||||
personalGroupManager.setStorage(personalGroupStorage);
|
||||
|
||||
MemberStorage memberStorage = new MemberStorage(dao);
|
||||
memberManager.setStorage(memberStorage);
|
||||
|
||||
ReinforcementStorage reinforcementStorage = new ReinforcementStorage(dao);
|
||||
reinforcementManager.setStorage(reinforcementStorage);
|
||||
}
|
||||
|
||||
public void registerCommands(){
|
||||
commandHandler.addCommand(new AddModCommand());
|
||||
commandHandler.addCommand(new AllowCommand());
|
||||
commandHandler.addCommand(new BypassCommand());
|
||||
commandHandler.addCommand(new CreateCommand());
|
||||
commandHandler.addCommand(new DeleteCommand());
|
||||
commandHandler.addCommand(new DisallowCommand());
|
||||
commandHandler.addCommand(new FortifyCommand());
|
||||
commandHandler.addCommand(new GroupCommand());
|
||||
commandHandler.addCommand(new GroupInfoCommand());
|
||||
commandHandler.addCommand(new GroupsCommand());
|
||||
//commandHandler.addCommand(new Help())
|
||||
commandHandler.addCommand(new InfoCommand());
|
||||
commandHandler.addCommand(new JoinCommand());
|
||||
commandHandler.addCommand(new LeaveCommand());
|
||||
commandHandler.addCommand(new MaterialsCommand());
|
||||
commandHandler.addCommand(new MembersCommand());
|
||||
commandHandler.addCommand(new ModeratorsCommand());
|
||||
commandHandler.addCommand(new NonReinforceableCommand());
|
||||
commandHandler.addCommand(new OffCommand());
|
||||
commandHandler.addCommand(new PasswordCommand());
|
||||
commandHandler.addCommand(new PrivateCommand());
|
||||
commandHandler.addCommand(new PublicCommand());
|
||||
commandHandler.addCommand(new ReinforceCommand());
|
||||
commandHandler.addCommand(new RemoveModCommand());
|
||||
commandHandler.addCommand(new SecurableCommand());
|
||||
commandHandler.addCommand(new StatsCommand());
|
||||
commandHandler.addCommand(new TransferCommand());
|
||||
commandHandler.addCommand(new VersionCommand());
|
||||
commandHandler.addCommand(new AddModCommand());
|
||||
commandHandler.addCommand(new AllowCommand());
|
||||
commandHandler.addCommand(new BypassCommand());
|
||||
commandHandler.addCommand(new CreateCommand());
|
||||
commandHandler.addCommand(new DeleteCommand());
|
||||
commandHandler.addCommand(new DisallowCommand());
|
||||
commandHandler.addCommand(new FortifyCommand());
|
||||
commandHandler.addCommand(new GroupCommand());
|
||||
commandHandler.addCommand(new GroupInfoCommand());
|
||||
commandHandler.addCommand(new GroupsCommand());
|
||||
//commandHandler.addCommand(new Help())
|
||||
commandHandler.addCommand(new InfoCommand());
|
||||
commandHandler.addCommand(new JoinCommand());
|
||||
commandHandler.addCommand(new LeaveCommand());
|
||||
commandHandler.addCommand(new MaterialsCommand());
|
||||
commandHandler.addCommand(new MembersCommand());
|
||||
commandHandler.addCommand(new ModeratorsCommand());
|
||||
commandHandler.addCommand(new NonReinforceableCommand());
|
||||
commandHandler.addCommand(new OffCommand());
|
||||
commandHandler.addCommand(new PasswordCommand());
|
||||
commandHandler.addCommand(new PrivateCommand());
|
||||
commandHandler.addCommand(new PublicCommand());
|
||||
commandHandler.addCommand(new ReinforceCommand());
|
||||
commandHandler.addCommand(new RemoveModCommand());
|
||||
commandHandler.addCommand(new SecurableCommand());
|
||||
commandHandler.addCommand(new StatsCommand());
|
||||
commandHandler.addCommand(new TransferCommand());
|
||||
commandHandler.addCommand(new VersionCommand());
|
||||
}
|
||||
|
||||
public void registerEvents(){
|
||||
try {
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
pm.registerEvents(new BlockListener(), this);
|
||||
pm.registerEvents(new PlayerListener(), this);
|
||||
pm.registerEvents(new EntityListener(), this);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
printStackTrace(e);
|
||||
}
|
||||
try {
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
pm.registerEvents(new BlockListener(), this);
|
||||
pm.registerEvents(new PlayerListener(), this);
|
||||
pm.registerEvents(new EntityListener(), this);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
printStackTrace(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -176,41 +176,41 @@ public class Citadel extends JavaPlugin {
|
||||
}
|
||||
|
||||
public static void info(String message){
|
||||
if(configManager.getVerboseLogging()){
|
||||
log.info("[Citadel] " + message);
|
||||
}
|
||||
if(configManager.getVerboseLogging()){
|
||||
log.info("[Citadel] " + message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void severe(String message){
|
||||
log.severe("[Citadel] " + message);
|
||||
log.severe("[Citadel] " + message);
|
||||
}
|
||||
|
||||
public static void warning(String message){
|
||||
log.warning("[Citadel] " + message);
|
||||
log.warning("[Citadel] " + message);
|
||||
}
|
||||
|
||||
public static GroupManager getGroupManager(){
|
||||
return groupManager;
|
||||
return groupManager;
|
||||
}
|
||||
|
||||
public static PersonalGroupManager getPersonalGroupManager(){
|
||||
return personalGroupManager;
|
||||
return personalGroupManager;
|
||||
}
|
||||
|
||||
public static MemberManager getMemberManager(){
|
||||
return memberManager;
|
||||
return memberManager;
|
||||
}
|
||||
|
||||
public static ReinforcementManager getReinforcementManager(){
|
||||
return reinforcementManager;
|
||||
return reinforcementManager;
|
||||
}
|
||||
|
||||
public static ConfigManager getConfigManager(){
|
||||
return configManager;
|
||||
return configManager;
|
||||
}
|
||||
|
||||
public static Citadel getPlugin(){
|
||||
return plugin;
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public static void printStackTrace(Throwable t)
|
||||
@@ -237,4 +237,4 @@ public class Citadel extends JavaPlugin {
|
||||
severe(" ======= SNIP HERE =======");
|
||||
severe("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
@@ -16,166 +17,174 @@ import com.untamedears.citadel.entity.Reinforcement;
|
||||
import com.untamedears.citadel.entity.ReinforcementKey;
|
||||
|
||||
public class CitadelCachingDao extends CitadelDao{
|
||||
HashMap<Chunk, ChunkCache> cachesByChunk;
|
||||
LinkedList<ChunkCache> cachesByTime;
|
||||
HashMap<Chunk, ChunkCache> cachesByChunk;
|
||||
LinkedList<ChunkCache> cachesByTime;
|
||||
|
||||
long maxAge;
|
||||
int maxChunks;
|
||||
|
||||
public CitadelCachingDao(JavaPlugin plugin){
|
||||
super(plugin);
|
||||
maxAge = Citadel.getConfigManager().getCacheMaxAge();
|
||||
maxChunks = Citadel.getConfigManager().getCacheMaxChunks();
|
||||
}
|
||||
|
||||
public ChunkCache getCacheOfBlock( Block block ) throws RefuseToPreventThrashingException {
|
||||
ChunkCache cache = cachesByChunk.get( block.getChunk() );
|
||||
if( cache != null ){
|
||||
cachesByTime.remove(cache);
|
||||
cachesByTime.add(cache);
|
||||
}else{
|
||||
if( cachesByTime.size() > maxChunks ){
|
||||
throw new RefuseToPreventThrashingException();
|
||||
}
|
||||
cache = new ChunkCache( block.getChunk() );
|
||||
cachesByChunk.put( block.getChunk() , cache );
|
||||
cachesByTime.add( cache );
|
||||
|
||||
ChunkCache last = cachesByTime.getLast();
|
||||
while( last.getLastPlooked() + maxAge < System.currentTimeMillis() ||
|
||||
cachesByTime.size() > maxChunks ){
|
||||
last.flush();
|
||||
cachesByTime.remove(last);
|
||||
cachesByChunk.remove(last.getChunk());
|
||||
}
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reinforcement findReinforcement( Location location ){
|
||||
return findReinforcement(location.getBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reinforcement findReinforcement( Block block ){
|
||||
try{
|
||||
ChunkCache cache = getCacheOfBlock( block );
|
||||
return cache.findReinforcement(block);
|
||||
}catch( RefuseToPreventThrashingException e ){
|
||||
Citadel.warning( "Bypassing RAM cache to prevent database thrashing. Consider raising caching.max_chunks");
|
||||
return super.findReinforcement( block );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Object o){
|
||||
if( o instanceof Reinforcement ){
|
||||
Reinforcement r = (Reinforcement)o;
|
||||
try{
|
||||
getCacheOfBlock( r.getBlock() ).save( r );
|
||||
}catch( RefuseToPreventThrashingException e ){
|
||||
Citadel.warning( "Bypassing RAM cache to prevent database thrashing. Consider raising caching.max_chunks");
|
||||
super.save( r );
|
||||
}
|
||||
}else{
|
||||
super.save( o );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Object o){
|
||||
if( o instanceof Reinforcement ){
|
||||
Reinforcement r = (Reinforcement)o;
|
||||
try{
|
||||
getCacheOfBlock( r.getBlock() ).save( r );
|
||||
}catch( RefuseToPreventThrashingException e ){
|
||||
Citadel.warning( "Bypassing RAM cache to prevent database thrashing. Consider raising caching.max_chunks");
|
||||
super.delete( r );
|
||||
}
|
||||
}else{
|
||||
super.delete( o );
|
||||
}
|
||||
}
|
||||
|
||||
//There should be some interface to implement that calls this automatically.
|
||||
public void shutDown(){
|
||||
while( !cachesByTime.isEmpty() ){
|
||||
cachesByTime.pop().flush();
|
||||
}
|
||||
}
|
||||
|
||||
private class ChunkCache {
|
||||
TreeSet<Reinforcement> toSave;//if RAM isn't a problem replace this with a HashSet.
|
||||
TreeSet<Reinforcement> toDelete;//if RAM isn't a problem replace this with a HashSet.
|
||||
|
||||
TreeSet<Reinforcement> cache;//if RAM isn't a problem replace this with a HashSet.
|
||||
|
||||
Chunk chunk;
|
||||
long lastPlooked;
|
||||
|
||||
public ChunkCache( Chunk chunk ){
|
||||
this.chunk = chunk;
|
||||
cache = new TreeSet<Reinforcement>( findReinforcementsInChunk( chunk ));
|
||||
}
|
||||
|
||||
public Reinforcement findReinforcement( Location l ){
|
||||
return findReinforcement(l.getBlock());
|
||||
}
|
||||
|
||||
public Reinforcement findReinforcement( Block block ){
|
||||
lastPlooked = System.currentTimeMillis();
|
||||
|
||||
Reinforcement key = new Reinforcement();
|
||||
key.setId(new ReinforcementKey(block));
|
||||
Reinforcement r = cache.floor( key );
|
||||
|
||||
if( r.equals(key) ){
|
||||
toSave.add(r);
|
||||
return r;
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void save( Reinforcement r ){
|
||||
lastPlooked = System.currentTimeMillis();
|
||||
if( !cache.add( r )){
|
||||
//Yes, this makes sense.
|
||||
//If we're editing the cache, then our new "r" will equal the old "r"
|
||||
//because reinforements are compared by their ReinforcementKeys, and the
|
||||
//new and old Reinforcements have the same key. So we're removing the reinforcement
|
||||
//from the set that matches the new "r" (which the old "r" does) and then adding
|
||||
//the new "r".
|
||||
cache.remove( r );
|
||||
cache.add( r );
|
||||
}
|
||||
toDelete.remove( r );
|
||||
toSave.add( r );
|
||||
}
|
||||
|
||||
public void delete( Reinforcement r ){
|
||||
lastPlooked = System.currentTimeMillis();
|
||||
cache.remove( r );
|
||||
toSave.remove( r );
|
||||
toDelete.add( r );
|
||||
}
|
||||
|
||||
public void flush(){
|
||||
getDatabase().save(toSave);
|
||||
getDatabase().delete(toDelete);
|
||||
}
|
||||
|
||||
public long getLastPlooked(){
|
||||
return lastPlooked;
|
||||
}
|
||||
|
||||
public Chunk getChunk(){
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
||||
private class RefuseToPreventThrashingException extends Exception{
|
||||
|
||||
}
|
||||
long maxAge;
|
||||
int maxChunks;
|
||||
|
||||
public CitadelCachingDao(JavaPlugin plugin){
|
||||
super(plugin);
|
||||
cachesByTime = new LinkedList<ChunkCache>();
|
||||
cachesByChunk = new HashMap<Chunk, ChunkCache>();
|
||||
maxAge = Citadel.getConfigManager().getCacheMaxAge();
|
||||
maxChunks = Citadel.getConfigManager().getCacheMaxChunks();
|
||||
}
|
||||
|
||||
public ChunkCache getCacheOfBlock( Block block ) throws RefuseToPreventThrashingException {
|
||||
ChunkCache cache = cachesByChunk.get( block.getChunk() );
|
||||
|
||||
|
||||
if( cache != null ){
|
||||
cachesByTime.remove(cache);
|
||||
cachesByTime.add(cache);
|
||||
}else{
|
||||
if( cachesByTime.size() > maxChunks ){
|
||||
throw new RefuseToPreventThrashingException();
|
||||
}
|
||||
cache = new ChunkCache( block.getChunk() );
|
||||
cachesByChunk.put( block.getChunk() , cache );
|
||||
cachesByTime.add( cache );
|
||||
|
||||
ChunkCache last = cachesByTime.getLast();
|
||||
while( (last.getLastPlooked() + maxAge < System.currentTimeMillis() ||
|
||||
cachesByTime.size() > maxChunks) &&
|
||||
!cachesByTime.isEmpty() ){
|
||||
last.flush();
|
||||
cachesByTime.remove(last);
|
||||
cachesByChunk.remove(last.getChunk());
|
||||
}
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reinforcement findReinforcement( Location location ){
|
||||
return findReinforcement(location.getBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reinforcement findReinforcement( Block block ){
|
||||
try{
|
||||
ChunkCache cache = getCacheOfBlock( block );
|
||||
return cache.findReinforcement(block);
|
||||
}catch( RefuseToPreventThrashingException e ){
|
||||
Citadel.warning( "Bypassing RAM cache to prevent database thrashing. Consider raising caching.max_chunks");
|
||||
return super.findReinforcement( block );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Object o){
|
||||
if( o instanceof Reinforcement ){
|
||||
Reinforcement r = (Reinforcement)o;
|
||||
try{
|
||||
getCacheOfBlock( r.getBlock() ).save( r );
|
||||
}catch( RefuseToPreventThrashingException e ){
|
||||
Citadel.warning( "Bypassing RAM cache to prevent database thrashing. Consider raising caching.max_chunks");
|
||||
super.save( r );
|
||||
}
|
||||
}else{
|
||||
super.save( o );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Object o){
|
||||
if( o instanceof Reinforcement ){
|
||||
Reinforcement r = (Reinforcement)o;
|
||||
try{
|
||||
getCacheOfBlock( r.getBlock() ).save( r );
|
||||
}catch( RefuseToPreventThrashingException e ){
|
||||
Citadel.warning( "Bypassing RAM cache to prevent database thrashing. Consider raising caching.max_chunks");
|
||||
super.delete( r );
|
||||
}
|
||||
}else{
|
||||
super.delete( o );
|
||||
}
|
||||
}
|
||||
|
||||
//There should be some interface to implement that calls this automatically.
|
||||
public void shutDown(){
|
||||
while( !cachesByTime.isEmpty() ){
|
||||
cachesByTime.pop().flush();
|
||||
}
|
||||
}
|
||||
|
||||
private class ChunkCache {
|
||||
TreeSet<Reinforcement> toSave;//if RAM isn't a problem replace this with a HashSet.
|
||||
TreeSet<Reinforcement> toDelete;//if RAM isn't a problem replace this with a HashSet.
|
||||
|
||||
TreeSet<Reinforcement> cache;//if RAM isn't a problem replace this with a HashSet.
|
||||
|
||||
Chunk chunk;
|
||||
long lastPlooked;
|
||||
|
||||
public ChunkCache( Chunk chunk ){
|
||||
this.chunk = chunk;
|
||||
cache = new TreeSet<Reinforcement>( findReinforcementsInChunk( chunk ));
|
||||
toSave = new TreeSet<Reinforcement>();
|
||||
toDelete = new TreeSet<Reinforcement>();
|
||||
lastPlooked = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public Reinforcement findReinforcement( Location l ){
|
||||
return findReinforcement(l.getBlock());
|
||||
}
|
||||
|
||||
public Reinforcement findReinforcement( Block block ){
|
||||
lastPlooked = System.currentTimeMillis();
|
||||
|
||||
Reinforcement key = new Reinforcement();
|
||||
key.setId(new ReinforcementKey(block));
|
||||
Reinforcement r = cache.floor( key );
|
||||
|
||||
if( r != null && r.equals(key) ){
|
||||
toSave.add(r);
|
||||
return r;
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void save( Reinforcement r ){
|
||||
lastPlooked = System.currentTimeMillis();
|
||||
if( !cache.add( r )){
|
||||
//Yes, this makes sense.
|
||||
//If we're editing the cache, then our new "r" will equal the old "r"
|
||||
//because reinforements are compared by their ReinforcementKeys, and the
|
||||
//new and old Reinforcements have the same key. So we're removing the reinforcement
|
||||
//from the set that matches the new "r" (which the old "r" does) and then adding
|
||||
//the new "r".
|
||||
cache.remove( r );
|
||||
cache.add( r );
|
||||
}
|
||||
toDelete.remove( r );
|
||||
toSave.add( r );
|
||||
}
|
||||
|
||||
public void delete( Reinforcement r ){
|
||||
lastPlooked = System.currentTimeMillis();
|
||||
cache.remove( r );
|
||||
toSave.remove( r );
|
||||
toDelete.add( r );
|
||||
}
|
||||
|
||||
public void flush(){
|
||||
getDatabase().save(toSave);
|
||||
getDatabase().delete(toDelete);
|
||||
}
|
||||
|
||||
public long getLastPlooked(){
|
||||
return lastPlooked;
|
||||
}
|
||||
|
||||
public Chunk getChunk(){
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
||||
private class RefuseToPreventThrashingException extends Exception{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user