1 14 15 package org.quickserver.net.server; 16 17 import java.util.*; 18 import java.io.*; 19 import java.net.*; 20 21 import org.quickserver.net.*; 22 import org.quickserver.util.pool.thread.*; 23 import org.quickserver.util.*; 24 import org.quickserver.net.server.impl.*; 25 26 import java.util.logging.*; 27 28 42 public class GhostSocketReaper extends Thread implements ServerHook { 43 private static Logger logger = Logger.getLogger(GhostSocketReaper.class.getName()); 44 45 private long time = 1; 46 private QuickServer quickserver; 47 private volatile boolean stopFlag; 48 49 private long timeOut = 0; 50 private long timeOutDelay = 0; 51 private ClientIdentifier clientIdentifier = null; 52 private List notifiedGhostList = Collections.synchronizedList(new ArrayList()); 53 54 public void initHook(QuickServer quickserver) { 55 this.quickserver = quickserver; 56 clientIdentifier = quickserver.getClientIdentifier(); 57 } 58 59 public boolean handleEvent(int event) { 60 if(event==ServerHook.POST_STARTUP) { 61 setDaemon(true); 63 stopFlag = false; 64 setName("GhostSocketReaper-For-("+quickserver+")"); 65 start(); 66 return true; 67 } else if(event==ServerHook.POST_SHUTDOWN) { 68 stopFlag = true; 70 return true; 71 } 72 return false; 73 } 74 75 public String info() { 76 StringBuffer sb = new StringBuffer (); 77 sb.append("GhostSocketReaper - ServerHook"); 78 return sb.toString(); 79 } 80 81 public void run() { 82 logger.fine("Starting GhostSocketReaper thread - "+quickserver.getName()); 83 if(quickserver.getTimeout()<=0) { 84 stopFlag = true; 85 logger.info("Timeout is less than 0, so will exit - "+quickserver.getName()); 86 return; 87 } 88 timeOut = quickserver.getTimeout(); 89 90 if(quickserver.getBasicConfig().getServerMode().getBlocking()==true) 91 timeOutDelay = 1000; 93 List ghostList = new ArrayList(); 94 long searchSleepTime = timeOut/2; 95 int failCount = 0; 96 boolean flag = false; 97 while(stopFlag==false) { 98 try { 99 try { 100 sleep(searchSleepTime); 101 } catch(InterruptedException ie) { 102 logger.warning("InterruptedException : " + ie.getMessage()); 103 } 104 105 if(failCount<4) { 106 flag = optimisticGhostSocketsFinder(ghostList); 107 if(flag==false) 108 failCount++; 109 else 110 failCount = 0; 111 } else { 112 syncGhostSocketsFinder(ghostList); 113 failCount = 0; 114 } 115 cleanGhostSockets(ghostList, true); 116 117 } catch(Exception e) { 118 logger.fine("Exception : " + e); 119 if(Assertion.isEnabled()) { 120 logger.finest("StackTrace:\n"+MyString.getStackTrace(e)); 121 } 122 } 123 } 125 while(stopFlag==true) { 127 try { 128 try { 129 sleep(searchSleepTime); 130 } catch(InterruptedException ie) { 131 logger.warning("InterruptedException : " + ie.getMessage()); 132 } 133 134 if(quickserver.isClosed()==false) { 135 break; 136 } 137 138 if(quickserver.getClientCount()<=0) { 139 try { 140 Thread.yield(); 141 sleep(1000); } catch(InterruptedException ie) { 143 logger.warning("InterruptedException : " + ie.getMessage()); 144 } 145 quickserver.closeAllPools(); 146 break; 147 } 148 } catch(Exception e) { 149 logger.fine("Exception : " + e); 150 if(Assertion.isEnabled()) { 151 logger.finest("StackTrace:\n"+MyString.getStackTrace(e)); 152 } 153 break; 154 } 155 } 156 logger.info("Returning from GhostSocketReaper thread - "+quickserver.getName()); 157 } 158 159 private long getCurrentTime() { 160 return new Date().getTime(); 161 } 162 163 private boolean optimisticGhostSocketsFinder(List list) { 164 Iterator iterator = null; 165 ClientHandler clientHandler = null; 166 int count = 0; 167 long currentTime = getCurrentTime(); 168 try { 169 iterator = clientIdentifier.findAllClient(); 170 175 176 while(iterator.hasNext()) { 177 count++; 178 if(count==60) { 179 currentTime = getCurrentTime(); count = 1; 181 } 182 clientHandler = (ClientHandler)iterator.next(); 183 184 checkClientHandlerForGhostSocket(clientHandler, currentTime, list); 185 186 if(list.size()>100) { 187 logger.finest("Found about 100 ghost sockets, lets clean.."); 188 break; 189 } 190 } } catch(ConcurrentModificationException e) { 192 return false; 194 } 195 return true; 196 } 197 198 private void syncGhostSocketsFinder(List list) { 199 Iterator iterator = null; 200 ClientHandler clientHandler = null; 201 int count = 0; 202 long currentTime = getCurrentTime(); 203 synchronized(clientIdentifier.getObjectToSynchronize()) { 204 iterator = clientIdentifier.findAllClient(); 205 if(iterator.hasNext()) 206 logger.finest("ENTER"); 207 208 while(iterator.hasNext()) { 209 count++; 210 if(count==60) { 211 currentTime = getCurrentTime(); count = 1; 213 } 214 clientHandler = (ClientHandler)iterator.next(); 215 216 checkClientHandlerForGhostSocket(clientHandler, currentTime, list); 217 218 if(list.size()>100) { 219 logger.finest("Found about 100 ghost sockets, lets clean.."); 220 break; 221 } 222 } } 224 } 225 226 private void cleanGhostSockets(List list, boolean checkTimeout) { 227 long currentTime = getCurrentTime(); 228 long commTime = 0; 229 long diff = -1; 230 ClientHandler clientHandler = null; 231 232 int size = list.size(); 233 for(int i=0;i<size;i++) { 234 try { 235 clientHandler = (ClientHandler) list.get(i); 236 237 if(((BasicClientHandler)clientHandler).getWillClean()==true) { 238 logger.finest("Not closing client "+clientHandler+", WillClean is true"); 239 continue; 240 } 241 242 if(checkTimeout) { 243 timeOut = clientHandler.getTimeout()+timeOutDelay; 244 if(clientHandler.getLastCommunicationTime()!=null) { 245 commTime = clientHandler.getLastCommunicationTime().getTime(); 246 diff = currentTime-commTime; 247 248 if(diff < timeOut && clientHandler.isClosed()==false) { 249 logger.finest("Not closing client "+clientHandler+ 250 ", must have been reassigned. CommTime(sec): " 251 +commTime/1000+", Diff(sec): "+diff/1000); 252 continue; 253 } 254 } 255 } 257 if(clientHandler.isClosed()==false) { 258 logger.finest("Closing client "+clientHandler.getName()); 259 try { 260 if(clientHandler.hasEvent(ClientEvent.RUN_BLOCKING)==true) { 261 clientHandler.closeConnection(); 262 } else { 263 if( ((NonBlockingClientHandler)clientHandler).getThreadAccessCount()!=0 ) { 264 clientHandler.closeConnection(); 265 266 Object obj = clientHandler.getInputStream(); 267 if(obj!=null) { 268 synchronized(obj) { 269 clientHandler.getInputStream().notifyAll(); 270 } 271 } 272 } else { 273 clientHandler.addEvent(ClientEvent.CLOSE_CON); 274 quickserver.getClientPool().addClient(clientHandler); 275 } 276 } 277 } catch(Exception er) { 278 logger.fine("Error closing client "+clientHandler); 279 clientHandler.forceClose(); 280 } 281 } else { 282 if(clientHandler.hasEvent(ClientEvent.RUN_BLOCKING)==false) { 283 logger.finest("Notifying IO of client "+clientHandler); 284 Object obj = clientHandler.getInputStream(); 285 if(obj==null) continue; 286 synchronized(obj) { 287 clientHandler.getInputStream().notifyAll(); 288 } 289 290 logger.finest("Returning objs to pool "+clientHandler); 291 if(quickserver.getClientDataPool()!=null && clientHandler.getClientData()!=null) 292 quickserver.getClientDataPool().returnObject(clientHandler.getClientData()); 293 294 logger.finest(Thread.currentThread().getName()+" returning "+getName()); 295 quickserver.getClientHandlerPool().returnObject(clientHandler); 296 } else { 297 logger.finest("Skipping closed "+clientHandler+" since in blocking mode.. this should clean up it self."); 298 } 299 } 300 } catch(Exception ee) { 301 logger.fine("Exception forcing the close : " + ee); 302 if(Assertion.isEnabled()) { 303 logger.finest("StackTrace:\n"+MyString.getStackTrace(ee)); 304 } 305 } 306 } list.clear(); 308 } 309 310 private void checkClientHandlerForGhostSocket(ClientHandler clientHandler, 311 long currentTime, List list) { 312 if(clientHandler==null) 313 return; 314 315 316 if(clientHandler.isOpen()==false) { 317 logger.finest("Not connected .. so returning ClientData and ClientHandler objects for : "+clientHandler); 318 list.add(clientHandler); 319 return; 320 } 321 322 if(clientHandler.getTimeout()<=0) { 323 return; 325 } 326 327 if(clientHandler.getLastCommunicationTime()==null) return; 328 329 long commTime = clientHandler.getLastCommunicationTime().getTime(); 330 long diff = currentTime-commTime; 331 332 long timeOut = clientHandler.getTimeout()+timeOutDelay; 333 if(diff >= timeOut) { 334 logger.finest("Closable client "+clientHandler+", Time diff(sec) : " + 335 diff/1000); 336 list.add(clientHandler); 337 } 338 } 339 } 340 | Popular Tags |