From 77fe240f3b622f737e5b77f92e2533a297aee35f Mon Sep 17 00:00:00 2001 From: Charles Smith Date: Sat, 29 Sep 2012 13:21:11 -0700 Subject: [PATCH] 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. --- .../src/com/untamedears/citadel/Citadel.java | 134 +++---- .../citadel/dao/CitadelCachingDao.java | 331 +++++++++--------- 2 files changed, 237 insertions(+), 228 deletions(-) diff --git a/plugins/citadel-paper/src/com/untamedears/citadel/Citadel.java b/plugins/citadel-paper/src/com/untamedears/citadel/Citadel.java index e63698c40..764f75801 100644 --- a/plugins/citadel-paper/src/com/untamedears/citadel/Citadel.java +++ b/plugins/citadel-paper/src/com/untamedears/citadel/Citadel.java @@ -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(""); } -} \ No newline at end of file +} diff --git a/plugins/citadel-paper/src/com/untamedears/citadel/dao/CitadelCachingDao.java b/plugins/citadel-paper/src/com/untamedears/citadel/dao/CitadelCachingDao.java index 988024876..80f44b5b4 100644 --- a/plugins/citadel-paper/src/com/untamedears/citadel/dao/CitadelCachingDao.java +++ b/plugins/citadel-paper/src/com/untamedears/citadel/dao/CitadelCachingDao.java @@ -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 cachesByChunk; - LinkedList cachesByTime; + HashMap cachesByChunk; + LinkedList 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 toSave;//if RAM isn't a problem replace this with a HashSet. - TreeSet toDelete;//if RAM isn't a problem replace this with a HashSet. - - TreeSet 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( 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(); + cachesByChunk = new HashMap(); + 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 toSave;//if RAM isn't a problem replace this with a HashSet. + TreeSet toDelete;//if RAM isn't a problem replace this with a HashSet. + + TreeSet 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( findReinforcementsInChunk( chunk )); + toSave = new TreeSet(); + toDelete = new TreeSet(); + 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{ + + } }