/** (C) Game Page Network, Inc., Confidential, All Rights Reserved */
// Reaper.java
// --paul@gamepage.net, 07dec97

import java.io.*;
import java.net.*;
import java.util.*;

/** Reaper shuts down file descriptors in its own thread,
 * so the calling program doesn't need to sleep/wait
 * for result (which might include timeouts).
 */
class Reaper extends Thread {
  // Club.main invokes this.
  private static boolean debug = false;
  private static Vector reapers = new Vector(5);

  public Reaper() {
    reapers.addElement(this);
  }

  public void run() {
    Thread.currentThread().setName("Reaper");
    while (true) {
      try {
	Club.sleep(5*60000);	// five minute siesta
	reap(false);
      }
      catch (Exception e) {
	Club.warning(e,"Reaper error");
      }
    }
  }

  private static void reap(boolean verbose) {
    Enumeration e = Client.elements();
    long now = System.currentTimeMillis();
    if (verbose)
      Club.log("reap begin "+Client.size());
    while (e.hasMoreElements()) {      
      Client c = (Client)e.nextElement();
      if (c.isIdle(now,30)) {	// bye bye sleeping birdie...
	c.log("idle reaper logout");
	Member member = c.getMember();
	String name = (member==null) ? "" : member.toString();
	Table.logout(member,"zombie "+member);
	if (verbose)
	  c.log("idle reaper close");
	c.close(true);
	if (verbose)
	  Club.log("idle reaper closed "+name);
      } else if (verbose) {
	c.log("not idle "+c.idleMinutes());
      }
    }
    if (verbose)
      Club.log("reap end");
  }

  public static void dump() {
    debug = true;
    boolean ok = false;
    for (int i=0; i<reapers.size(); i++) {
      Thread thread = (Thread)reapers.elementAt(i);
      Club.log("reaper "+thread.countStackFrames()+
	       " Pri"+thread.getPriority()+
	       " Alive="+thread.isAlive()+
	       " Daemon="+thread.isDaemon()+
	       " Int="+thread.isInterrupted());
      if (!ok)
	ok = thread.isAlive();
    }
    Club.log("dump.reap "+ok);
    reap(true);			// verbose
  }
}
