1 24 25 package com.mckoi.database.jdbcserver; 26 27 import com.mckoi.database.User; 28 import com.mckoi.database.Database; 29 import com.mckoi.database.DatabaseSystem; 30 import com.mckoi.debug.*; 31 import java.io.IOException ; 32 import java.util.ArrayList ; 33 import java.util.LinkedList ; 34 import java.util.ResourceBundle ; 35 36 52 53 final class SingleThreadedConnectionPoolServer 54 implements ConnectionPoolServer { 55 56 61 private static final int PING_BREAK = 45 * 1000; 63 67 private static final boolean DISPLAY_STATS = false; 68 69 72 private Database database; 73 74 78 private ArrayList pending_connections_list; 79 80 84 private ServerFarmer farmer; 85 86 87 90 SingleThreadedConnectionPoolServer(Database database) { 91 this.database = database; 92 pending_connections_list = new ArrayList (); 93 farmer = new ServerFarmer(); 95 farmer.start(); 96 } 97 98 101 public final DebugLogger Debug() { 102 return database.Debug(); 103 } 104 105 111 public void addConnection(ServerConnection connection) { 112 synchronized(pending_connections_list) { 113 pending_connections_list.add(connection); 114 } 115 } 116 117 120 public void close() { 121 farmer.close(); 122 } 123 124 126 130 private class ServerFarmer extends Thread { 131 132 136 private ArrayList server_connections_list; 137 138 141 private int stat_display = 0; 142 private int commands_run = 0; 143 private int commands_waited = 0; 144 145 148 private boolean farmer_closed; 149 150 155 private int poll_wait_time; 156 157 158 159 162 public ServerFarmer() { 163 super(); 164 166 poll_wait_time = 3; 169 170 server_connections_list = new ArrayList (); 171 farmer_closed = false; 172 } 173 174 178 private void establishPendingConnections() throws IOException { 179 synchronized (pending_connections_list) { 180 int len = pending_connections_list.size(); 181 for (int i = 0; i < len; ++i) { 183 ServerConnection connection = 185 (ServerConnection) pending_connections_list.remove(0); 186 server_connections_list.add(new ServerConnectionState(connection)); 187 } 188 } 189 } 190 191 197 private void checkCurrentConnections() { 198 int len = server_connections_list.size(); 199 for (int i = len - 1; i >= 0; --i) { 200 ServerConnectionState connection_state = 201 (ServerConnectionState) server_connections_list.get(i); 202 try { 203 if (!connection_state.isProcessingRequest()) { 205 ServerConnection connection = connection_state.getConnection(); 206 if (connection_state.hasPendingCommand() || 208 connection.requestPending()) { 209 connection_state.setPendingCommand(); 211 connection_state.setProcessingRequest(); 212 213 final ServerConnectionState current_state = connection_state; 214 215 database.execute(null, null, new Runnable () { 220 public void run() { 221 222 try { 223 current_state.getConnection().processRequest(); 225 } 226 catch (IOException e) { 227 Debug().writeException(Lvl.INFORMATION, e); 228 } 229 finally { 230 current_state.clearInternal(); 234 } 235 236 } 237 }); 238 239 } } } 242 catch (IOException e) { 243 try { 246 connection_state.getConnection().close(); 247 } 248 catch (IOException e2) { } 249 server_connections_list.remove(i); 250 251 Debug().write(Lvl.INFORMATION, this, 253 "IOException generated while checking connections, " + 254 "removing provider."); 255 Debug().writeException(Lvl.INFORMATION, e); 256 } 257 } 258 } 259 260 264 private void doPings() { 265 int len = server_connections_list.size(); 266 if (len == 0) { 267 if (DISPLAY_STATS) { 268 System.out.print("[TCPServer Stats] "); 269 System.out.println("Ping tried but no connections."); 270 } 271 return; 272 } 273 int i = (int) (Math.random() * len); 274 275 if (DISPLAY_STATS) { 276 System.out.print("[TCPServer Stats] "); 277 System.out.print("Pinging client "); 278 System.out.print(i); 279 System.out.println("."); 280 } 281 282 final ServerConnectionState connection_state = 283 (ServerConnectionState) server_connections_list.get(i); 284 285 if (!connection_state.isProcessingRequest()) { 287 connection_state.setProcessingRequest(); 289 290 database.execute(null, null, new Runnable () { 292 public void run() { 293 try { 294 connection_state.getConnection().ping(); 297 } 298 catch (IOException e) { 299 try { 301 connection_state.getConnection().close(); 302 } 303 catch (IOException e2) { } 304 Debug().write(Lvl.ALERT, ServerFarmer.this, 305 "Closed because ping failed."); 306 Debug().writeException(Lvl.ALERT, e); 307 } 308 finally { 309 connection_state.clearProcessingRequest(); 310 } 311 } 312 }); 313 314 } } 316 317 320 private void displayStatistics() { 321 if (DISPLAY_STATS) { 322 if (stat_display == 0) { 323 stat_display = 500; 324 System.out.print("[TCPServer Stats] "); 325 System.out.print(commands_run); 326 System.out.print(" run, "); 327 System.out.print(commands_waited); 328 System.out.print(" wait, "); 329 System.out.print(server_connections_list.size()); 330 System.out.print(" worker count"); 331 System.out.println(); 332 } 333 else { 334 --stat_display; 335 } 336 } 337 } 338 339 342 public synchronized void close() { 343 farmer_closed = true; 344 } 345 346 349 public void run() { 350 int yield_count = 0; 351 long do_ping_time = System.currentTimeMillis() + PING_BREAK; 352 int ping_count = 200; 353 354 final int method_poll_wait_time = poll_wait_time; 355 356 Debug().write(Lvl.MESSAGE, this, 357 "Polling frequency: " + method_poll_wait_time + "ms."); 358 359 while (true) { 360 try { 361 362 if (pending_connections_list.size() > 0) { 365 establishPendingConnections(); 366 } 367 checkCurrentConnections(); 368 369 --ping_count; 371 if (ping_count <= 0) { 372 ping_count = 2000; 373 long current_time = System.currentTimeMillis(); 374 if (current_time > do_ping_time) { 375 doPings(); 377 do_ping_time = current_time + PING_BREAK; 378 } 379 } 380 381 if (yield_count <= 0) { 382 synchronized (this) { 383 wait(method_poll_wait_time); 385 yield_count = 3; 386 } 387 } 388 else { 389 synchronized (this) { 390 if (farmer_closed == true) { 392 return; 393 } 394 } 395 Thread.yield(); 396 --yield_count; 397 } 398 399 displayStatistics(); 401 402 } 403 catch (Throwable e) { 404 Debug().write(Lvl.ERROR, this, "Connection Pool Farmer Error"); 405 Debug().writeException(e); 406 407 synchronized (this) { 409 try { 410 wait(2000); 411 } 412 catch (InterruptedException e2) { } 413 } 414 415 } 416 } 417 } 418 419 }; 420 421 422 426 private final class ServerConnectionState { 427 428 431 private ServerConnection connection; 432 private boolean is_processing_request; 434 private boolean is_pending_command; 435 private boolean is_ping_client; 436 437 440 ServerConnectionState(ServerConnection connection) { 441 this.connection = connection; 442 clearInternal(); 443 } 445 446 449 public synchronized void setProcessingRequest() { 450 is_processing_request = true; 451 } 452 public synchronized void setPendingCommand() { 453 is_pending_command = true; 454 } 455 public synchronized void setPingClient() { 456 is_ping_client = true; 457 } 458 459 460 463 public synchronized void clearInternal() { 464 is_processing_request = false; 465 is_pending_command = false; 466 is_ping_client = false; 468 } 469 470 473 public synchronized void clearProcessingRequest() { 474 is_processing_request = false; 475 } 476 477 480 public synchronized ServerConnection getConnection() { 481 return connection; 482 } 483 public synchronized boolean isProcessingRequest() { 484 return is_processing_request; 485 } 486 public synchronized boolean hasPendingCommand() { 487 return is_pending_command; 488 } 489 public synchronized boolean isPingClient() { 493 return is_ping_client; 494 } 495 496 } 497 498 } 499 | Popular Tags |