]> jfr.im git - irc/rizon/acid.git/commitdiff
Conversion from timers to netty scheduled tasks
authorAdam <redacted>
Sun, 4 Sep 2016 22:59:28 +0000 (18:59 -0400)
committerAdam <redacted>
Sun, 4 Sep 2016 22:59:28 +0000 (18:59 -0400)
acid/src/main/java/net/rizon/acid/core/AcidCore.java
acid/src/main/java/net/rizon/acid/core/Acidictive.java
acid/src/main/java/net/rizon/acid/core/FutureExceptionListener.java [new file with mode: 0644]
acid/src/main/java/net/rizon/acid/core/Timer.java [deleted file]
pyva/pyva/src/main/java/net/rizon/acid/plugins/pyva/pyva/pyva.java
trapbot/src/main/java/net/rizon/acid/plugins/trapbot/ExpireTimer.java
trapbot/src/main/java/net/rizon/acid/plugins/trapbot/ReleaseTimer.java
trapbot/src/main/java/net/rizon/acid/plugins/trapbot/RetrapTimer.java
trapbot/src/main/java/net/rizon/acid/plugins/trapbot/trapbot.java

index 08bb473667d059d08bd06276558d967e908a8369..d82a7d1d3223ab69751dbd9bc4e433fc697dfb7f 100644 (file)
@@ -24,7 +24,7 @@ public abstract class AcidCore
        public static String uplink, password;
        public static int port;
 
-       private static final EventLoopGroup eventLoop = new NioEventLoopGroup(1);
+       protected static final EventLoopGroup eventLoop = new NioEventLoopGroup(1);
        private static io.netty.channel.Channel channel;
 
        public static void start(String server, int port, String name, String description, String password, String SID, boolean ssl)
@@ -92,8 +92,6 @@ public abstract class AcidCore
 //                     b.close();
 //             }
 
-               Timer.processTimers();
-
                Message m = Message.findMessage(message.getCommand());
                if (m == null)
                {
index 586eac78e9d6ddd35cd91445ff4c2f85fa826ef9..9275bf9220c98987f569c3feb515a28298b1f8f2 100644 (file)
@@ -1,5 +1,6 @@
 package net.rizon.acid.core;
 
+import io.netty.util.concurrent.ScheduledFuture;
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileWriter;
@@ -11,6 +12,7 @@ import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 import net.rizon.acid.conf.Client;
 import net.rizon.acid.conf.Config;
 import net.rizon.acid.sql.SQL;
@@ -772,4 +774,38 @@ public class Acidictive extends AcidCore
                                au.introduce();
                }
        }
+
+       public static ScheduledFuture scheduleWithFixedDelay(Runnable r, long t, TimeUnit unit)
+       {
+               ScheduledFuture future = eventLoop.scheduleWithFixedDelay(r, t, t, unit);
+               FutureExceptionListener listener = new FutureExceptionListener();
+
+               listener.setRescheduleParameters(r, t, t, unit, FutureExceptionListener.ScheduleType.FIXED_DELAY);
+
+               future.addListener(listener);
+
+               return future;
+       }
+
+       public static ScheduledFuture scheduleAtFixedRate(Runnable r, long t, TimeUnit unit)
+       {
+               ScheduledFuture future = eventLoop.scheduleAtFixedRate(r, t, t, unit);
+               FutureExceptionListener listener = new FutureExceptionListener();
+
+               listener.setRescheduleParameters(r, t, t, unit, FutureExceptionListener.ScheduleType.FIXED_RATE);
+
+               future.addListener(listener);
+
+               return future;
+       }
+
+       public static ScheduledFuture schedule(Runnable r, long t, TimeUnit unit)
+       {
+               ScheduledFuture future = eventLoop.schedule(r, t, unit);
+               FutureExceptionListener listener = new FutureExceptionListener();
+
+               future.addListener(listener);
+
+               return future;
+       }
 }
diff --git a/acid/src/main/java/net/rizon/acid/core/FutureExceptionListener.java b/acid/src/main/java/net/rizon/acid/core/FutureExceptionListener.java
new file mode 100644 (file)
index 0000000..897f45f
--- /dev/null
@@ -0,0 +1,77 @@
+package net.rizon.acid.core;
+
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.FutureListener;
+import java.util.concurrent.TimeUnit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Reports any errors when a future operation is completed and is not completed
+ * successfully or canceled.
+ * <p>
+ * @author Orillion {@literal <orillion@rizon.net>}
+ */
+public class FutureExceptionListener<T> implements FutureListener<T>
+{
+       private static final Logger logger = LoggerFactory.getLogger(FutureExceptionListener.class);
+
+       public enum ScheduleType
+       {
+               FIXED_DELAY,
+               FIXED_RATE
+       }
+
+       private boolean reschedule = false;
+       private Runnable runnable;
+       private long delay;
+       private long timer;
+       private TimeUnit timeUnit;
+       private ScheduleType scheduleType;
+
+       @Override
+       public void operationComplete(Future<T> future) throws Exception
+       {
+               if (future.isSuccess() || future.isCancelled())
+               {
+                       return;
+               }
+
+               Throwable t = future.cause();
+
+               logger.error("Scheduled operation failed: " + t.toString(), t);
+
+               if (this.reschedule)
+               {
+                       switch (this.scheduleType)
+                       {
+                               case FIXED_DELAY:
+                                       Acidictive.scheduleWithFixedDelay(this.runnable, this.timer, this.timeUnit);
+                                       break;
+                               case FIXED_RATE:
+                                       Acidictive.scheduleAtFixedRate(this.runnable, this.timer, this.timeUnit);
+                                       break;
+                       }
+               }
+       }
+
+       /**
+        * Sets the parameters in case this future needs to reschedule itself when
+        * it throws an exception.
+        * <p>
+        * @param r     Runnable to run
+        * @param delay Initial delay
+        * @param timer Period between timings
+        * @param unit  TimeUnit
+        * @param type  Type of schedule to use
+        */
+       public void setRescheduleParameters(Runnable r, long delay, long timer, TimeUnit unit, ScheduleType type)
+       {
+               this.reschedule = true;
+               this.runnable = r;
+               this.delay = delay;
+               this.timer = timer;
+               this.timeUnit = unit;
+               this.scheduleType = type;
+       }
+}
diff --git a/acid/src/main/java/net/rizon/acid/core/Timer.java b/acid/src/main/java/net/rizon/acid/core/Timer.java
deleted file mode 100644 (file)
index 508304f..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-package net.rizon.acid.core;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class Timer
-{
-       private static final Logger log = LoggerFactory.getLogger(Timer.class);
-       
-       private static ArrayList<Timer> timers = new ArrayList<Timer>();
-
-       public Date creation;
-       public Date tick;
-       public long time_from_now;
-       public boolean repeating;
-       private boolean dead;
-
-       public Timer(long time_from_now, boolean repeating)
-       {
-               this.creation = new Date();
-               this.tick = new Date(System.currentTimeMillis() + (time_from_now * 1000));
-               this.time_from_now = time_from_now;
-               this.repeating = repeating;
-               this.dead = false;
-       }
-
-       public void start()
-       {
-               timers.add(this);
-       }
-
-       public void stop()
-       {
-               this.dead = true;
-       }
-
-       public abstract void run(final Date now);
-
-       public static void processTimers()
-       {
-               Date now = new Date();
-
-               // Timers can be added from Timer;:run, which will modify this list.
-               // Iterate by indexes instead going backward.
-               for (int i = timers.size(); i >  0; --i)
-               {
-                       Timer t = timers.get(i - 1);
-
-                       if (t.dead == false && now.after(t.tick))
-                       {
-                               try
-                               {
-                                       t.run(now);
-                               }
-                               catch (Exception ex)
-                               {
-                                       log.error("Error running timer", ex);
-                               }
-                               if (t.repeating == false)
-                                       t.stop();
-                               else
-                                       t.tick = new Date(System.currentTimeMillis() + (t.time_from_now * 1000));
-                       }
-               }
-
-               for (Iterator<Timer> it = timers.iterator(); it.hasNext();)
-               {
-                       Timer t = it.next();
-
-                       if (t.dead == true)
-                               it.remove();
-               }
-       }
-}
\ No newline at end of file
index d85511df09328368601db28dd42dddd59a805e84..5e28ca1e9611dc42209786244c52402340a1c3db 100644 (file)
@@ -1,12 +1,12 @@
 package net.rizon.acid.plugins.pyva.pyva;
 
+import io.netty.util.concurrent.ScheduledFuture;
 import java.util.Arrays;
-import java.util.Date;
+import java.util.concurrent.TimeUnit;
 import net.rizon.acid.core.Acidictive;
 import net.rizon.acid.core.Channel;
 import net.rizon.acid.core.Event;
 import net.rizon.acid.core.Plugin;
-import net.rizon.acid.core.Timer;
 import net.rizon.acid.core.User;
 import net.rizon.acid.plugins.pyva.pyva.conf.Config;
 import net.rizon.pyva.Pyva;
@@ -116,15 +116,10 @@ class PyvaEvent extends Event
        }
 }
 
-class GCTimer extends Timer
+class GCTimer implements Runnable
 {
-       public GCTimer()
-       {
-               super(60, true);
-       }
-
        @Override
-       public void run(Date now)
+       public void run()
        {
                System.gc();
                pyva.pyva.gc();
@@ -136,7 +131,7 @@ public class pyva extends Plugin
        protected static final Logger log = LoggerFactory.getLogger(pyva.class);
 
        private Config conf;
-       private Timer t;
+       private ScheduledFuture gcTimer;
        public static Pyva pyva;
 
        private Event e;
@@ -166,14 +161,13 @@ public class pyva extends Plugin
                
                e = new PyvaEvent();
 
-               t = new GCTimer();
-               t.start();
+               Acidictive.scheduleWithFixedDelay(new GCTimer(), 1, TimeUnit.MINUTES);
        }
 
        @Override
        public void stop()
        {
-               t.stop();
+               gcTimer.cancel(true);
 
                e.remove();
 
index 6471b19cbc158407fd9c61881ba3d1af63370c05..14399b8345186cbba1cee0f42d0a9ee62f226c2a 100644 (file)
@@ -3,19 +3,14 @@ package net.rizon.acid.plugins.trapbot;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.Map;
-import net.rizon.acid.core.Timer;
 
-class ExpireTimer extends Timer
+class ExpireTimer implements Runnable
 {
-       ExpireTimer()
-       {
-               // one day
-               super(60 * 60 * 24, true);
-       }
-
        @Override
-       public void run(Date now)
+       public void run()
        {
+               Date now = new Date();
+               
                for (Iterator<Map.Entry<String, TrappedUser>> it = trapbot.users.entrySet().iterator(); it.hasNext();)
                {
                        Map.Entry<String, TrappedUser> e = it.next();
index 86af32feb9094c3189ec7c869f5a7d97ed879242..8b44cee0891415a273162c9dfe924dd3452da784 100644 (file)
@@ -1,28 +1,20 @@
 package net.rizon.acid.plugins.trapbot;
 
-import java.util.Date;
-import java.util.Random;
+import java.util.concurrent.TimeUnit;
+import net.rizon.acid.core.Acidictive;
 import net.rizon.acid.core.Message;
 import net.rizon.acid.core.Protocol;
-import net.rizon.acid.core.Timer;
 
-class ReleaseTimer extends Timer
+class ReleaseTimer implements Runnable
 {
-       ReleaseTimer()
-       {
-               // XXX magic?
-               super(new Random().nextInt(2700) + 2700, false);
-       }
-
        @Override
-       public void run(final Date now)
+       public void run()
        {
                Protocol.privmsg(trapbot.trapbot.getUID(), trapbot.getTrapChanName(), Message.BOLD + "YOU HAVE 1 MINUTE TO PART THE CHANNEL, GET OUT WHILE YOU CAN!" + Message.BOLD);
 
                trapbot.enforce = false;
                trapbot.releaseTimer = null;
 
-               trapbot.retrapTimer = new RetrapTimer(60, false);
-               trapbot.retrapTimer.start();
+               trapbot.retrapTimer = Acidictive.schedule(new RetrapTimer(), 1, TimeUnit.MINUTES);
        }
 }
index d2dbd998c1f66a244cc017ef050f739ff214de76..436fde0c9d9ed25c0040c4cdaaf50f2f10908086 100644 (file)
@@ -1,22 +1,18 @@
 package net.rizon.acid.plugins.trapbot;
 
-import java.util.Date;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+import net.rizon.acid.core.Acidictive;
 import net.rizon.acid.core.Message;
 import net.rizon.acid.core.Protocol;
-import net.rizon.acid.core.Timer;
 
-class RetrapTimer extends Timer
+class RetrapTimer implements Runnable
 {
-       RetrapTimer(long time_from_now, boolean repeating)
-       {
-               super(time_from_now, repeating);
-       }
-
        /*
         * release users
         */
        @Override
-       public void run(final Date now)
+       public void run()
        {
                /* start enforcing again and announce it */
                trapbot.enforce = true;
@@ -24,7 +20,7 @@ class RetrapTimer extends Timer
 
                Protocol.privmsg(trapbot.trapbot.getUID(), trapbot.getTrapChanName(), Message.BOLD + "HAHA TRAPPED AGAIN!" + Message.BOLD);
 
-               trapbot.releaseTimer = new ReleaseTimer();
-               trapbot.releaseTimer.start();
+               // magic here, too
+               trapbot.releaseTimer = Acidictive.schedule(new ReleaseTimer(), new Random().nextInt(2700) + 2700, TimeUnit.SECONDS);
        }
 }
index d8393f9afd4c503df6af07a2d79fb232acd8b2e5..1679e8878e33a06ea37c3996248541b63e08fb0c 100644 (file)
@@ -1,12 +1,14 @@
 package net.rizon.acid.plugins.trapbot;
 
+import io.netty.util.concurrent.ScheduledFuture;
 import java.util.HashMap;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
 import net.rizon.acid.core.AcidCore;
 import net.rizon.acid.core.AcidUser;
 import net.rizon.acid.core.Acidictive;
 import net.rizon.acid.core.Event;
 import net.rizon.acid.core.Plugin;
-import net.rizon.acid.core.Timer;
 import net.rizon.acid.core.User;
 import net.rizon.acid.plugins.trapbot.conf.Config;
 import org.slf4j.Logger;
@@ -19,9 +21,9 @@ public class trapbot extends Plugin
        private Event ev;
        public static AcidUser trapbot;
        public static Config conf;
-       private Timer expireTimer;
-       public static Timer retrapTimer;
-       public static Timer releaseTimer;
+       private ScheduledFuture expireTimer;
+       public static ScheduledFuture retrapTimer;
+       public static ScheduledFuture releaseTimer;
        // ip -> user
        public static HashMap<String, TrappedUser> users = new HashMap<String, TrappedUser>();
        public static boolean enforce = true;
@@ -75,11 +77,10 @@ public class trapbot extends Plugin
 
                reload();
 
-               expireTimer = new ExpireTimer();
-               expireTimer.start();
+               expireTimer = Acidictive.scheduleWithFixedDelay(new ExpireTimer(), 1, TimeUnit.DAYS);
 
-               releaseTimer = new ReleaseTimer();
-               releaseTimer.start();
+               // magic!
+               releaseTimer = Acidictive.schedule(new ReleaseTimer(), new Random().nextInt(2700) + 2700, TimeUnit.SECONDS);
        }
 
        @Override
@@ -101,12 +102,12 @@ public class trapbot extends Plugin
                ev.remove();
 
                if (expireTimer != null)
-                       expireTimer.stop();
+                       expireTimer.cancel(true);
 
                if (releaseTimer != null)
-                       releaseTimer.stop();
+                       releaseTimer.cancel(true);
 
                if (retrapTimer != null)
-                       retrapTimer.stop();
+                       retrapTimer.cancel(true);
        }
 }