package jeffaschenk.commons.frameworks.cnxidx.resiliency.ldap;
import jeffaschenk.commons.frameworks.cnxidx.utility.StopWatch;
import jeffaschenk.commons.frameworks.cnxidx.utility.ldap.idxLapTime;
import jeffaschenk.commons.frameworks.cnxidx.utility.logging.FrameworkLogger;
import jeffaschenk.commons.frameworks.cnxidx.utility.logging.FrameworkLoggerLevel;
import jeffaschenk.commons.touchpoint.model.threads.CircularObjectStack;
import java.nio.channels.Selector;
import java.util.*;
/**
* Change Log Restore WEB Admin Thread. Creates an Embedded WEB Server to
* serve up status and provide operational ability to the end customer
* to operate the Change Log Restore Facility.
*
* @author jeff.schenk
* @version 4.4 $Revision
* Developed 2005
*/
/**
* WebAdminServerThread
* Class to run Embedded Web Admin Thread.
*/
class WebAdminServerThread implements Runnable {
// *******************************
// Common Logging Facility.
private static final String CLASSNAME
= WebAdminServerThread.class.getName();
/**
* WebAdminServerThread
* Class to provide Web Admin Interface to Log Restore Facility.
*/
Thread t;
private static final String THREAD_NAME
= "ServiceWebAdminThread";
private IRRChangeLogRestoreServiceControlThread
CONTROL_THREAD = null; // Provides interface to Local Cmds.
private CircularObjectStack cosin; // Input Stack.
private CircularObjectStack cosout; // Output to Publisher Stack.
private int WEBADMIN_PORT; // Embedded Web Server Port.
// *************************************
// NIO Socket Channel Objects.
private WebAdminAcceptorThread acceptor = null;
private WebAdminResponderThread responder = null;
// ***********************************************
// Initialize my LAP Timers
private idxLapTime LP_ENTRY_TO_COS = new idxLapTime();
private idxLapTime LP_ENTRY_FROM_COS = new idxLapTime();
// ***********************************************
// Allow List for Client Requests.
private LinkedList WEBADMIN_ALLOW_LIST = null;
/**
* IRRBackupOutputThread Contructor class driven.
*
* @param cosin Circular Object Stack for Obtaining Control Commands.
* @param cosout Circular Object Stack for placing LDAP Entries on Output Stack.
* @param WEBADMIN_PORT HTTP port to start embedded web server.
*/
public WebAdminServerThread(
IRRChangeLogRestoreServiceControlThread CONTROL_THREAD,
CircularObjectStack cosin,
CircularObjectStack cosout,
int WEBADMIN_PORT,
LinkedList WEBADMIN_ALLOW_LIST) {
// ****************************************
// Set My Incoming Parameters.
this.CONTROL_THREAD = CONTROL_THREAD;
this.cosin = cosin;
this.cosout = cosout;
this.WEBADMIN_PORT = WEBADMIN_PORT;
this.WEBADMIN_ALLOW_LIST = WEBADMIN_ALLOW_LIST;
// ****************************************
// Ready the Synchronized Object and start
// the Thread.
t = new Thread(this, WebAdminServerThread.THREAD_NAME);
t.start(); // Start the Thread
} // End of Contructor.
/**
* run
* Thread to Provide Web Admin Interface to the JGroups Cloud.
*/
public void run() {
// ***********************************************
// Initialize our StopWatch to measure Duration
// of Thread.
final String METHODNAME = "run";
StopWatch sw = new StopWatch();
sw.start();
// ***********************************************
// Initialize Thread Variables.
StackCommand instackcommand = null;
boolean running = false;
int ecount = 0;
// ***********************************************
// Initialize our Web Interface.
while (!running) {
try {
this.init();
running = true;
} catch (Exception ioe) {
if (ecount == 0) {
FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.SEVERE,
ErrorConstants.WEBADMIN_OBTAINING_HTTP_SOCKET_EXCEPTION,
new String[]{Integer.toString(this.WEBADMIN_PORT), ioe.toString()});
} else if (ecount > 1000) {
ecount = 0;
}
try {
Thread.sleep(20000);
} catch (InterruptedException ie) {
}
} // End of Exception Processing.
} // End of Loop to Start the HTTP Socket.
// *************************************************
// Indicate we have established the Socket, so ready
// to enter our main Loop.
//
FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO,
MessageConstants.WEBADMIN_THREAD_ESTABLISHED,
new String[]{Thread.currentThread().getName()});
// ******************************************
// Loop to process commands from our
// Input Stack, if it is not a End of Thread
// place it back on the stack.
while (running) {
instackcommand = null; // Be sure to Clear Previous Entry.
LP_ENTRY_FROM_COS.Start();
if (cosin.hasMoreNodes()) {
instackcommand = (StackCommand) cosin.getNext();
}
LP_ENTRY_FROM_COS.Stop();
// ***************************
// Did anything get pulled
// from stack?
if (instackcommand != null) {
// ******************************
// Did our Running State trip to
// not based upon a End of Thread
// command? If so, never place this
// Command on the BUS.
if (instackcommand.getCommandType() ==
StackCommand.CL_END_OF_THREAD) {
running = false;
continue; // Force our loop to End.
} // End of Check for End of Thread.
// *************************************
// We need to place whatever we took off
// the Stack Back on as this command
// was probably meant for a Client
// Web Thread.
cosin.push(instackcommand);
} // End of Nothing in Stack yet to Process.
else {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
}
} // End of Else.
} // End of Main While Loop.
// ***************************************
// Shutdown our Child Threads.
FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO,
MessageConstants.WEBADMIN_THREAD_SHUTDOWN_CHILD_THREADS);
this.acceptor.shutdown();
this.responder.shutdown();
// ***************************************
// Now wait for Threads to finish, if they
// have not already.
try {
acceptor.join();
} catch (InterruptedException e) {
// NOOP.
} // End of Exception.
try {
responder.join();
} catch (InterruptedException e) {
// NOOP.
} // End of Exception.
// ***************************************
// Show the Lap Timings.
FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO,
MessageConstants.WEBADMIN_LAPTIME_FROM_STACK,
new String[]{LP_ENTRY_FROM_COS.toString()});
FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO,
MessageConstants.WEBADMIN_LAPTIME_TO_STACK,
new String[]{LP_ENTRY_TO_COS.toString()});
// ***************************************
// Show the Duration of Thread.
sw.stop();
FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO,
MessageConstants.WEBADMIN_THREAD_SHUTDOWN,
new String[]{sw.getElapsedTimeString()});
// ***************************************
// Done.
return;
} // End of run.
/**
* Get Current Component Status.
*
* @return String Data Representing Current Status of this Component.
*/
protected String getStatus() {
StringBuffer sb = new StringBuffer();
// **************************************
// Build String Buffer with Status for
// this component.
// **************************************
// Show Header
sb.append(WebAdminResponderThread.COMPONENT_BEGIN);
sb.append("WEB ADMIN Thread");
sb.append(WebAdminResponderThread.COMPONENT_END);
// **************************************
// Show Detail.
sb.append(WebAdminResponderThread.BEGIN_TABLE);
sb.append(WebAdminResponderThread.build2ColumnRow("Web Admin Port",
Integer.toString(this.WEBADMIN_PORT)));
// ***********************************
// Check Acceptor Child Thread Status
if (this.acceptor != null) {
if (this.acceptor.isAlive()) {
sb.append(WebAdminResponderThread.build2ColumnRow("Acceptor SubThread Active",
WebAdminResponderThread.POSITIVE_VALUE +
Boolean.toString(this.acceptor.isAlive()) +
WebAdminResponderThread.POSITIVE_VALUE_END));
} else {
sb.append(WebAdminResponderThread.build2ColumnRow("Acceptor SubThread Active",
WebAdminResponderThread.CAUTION_VALUE +
Boolean.toString(this.acceptor.isAlive()) +
WebAdminResponderThread.CAUTION_VALUE_END));
} // End of Inner Else.
} else {
sb.append(WebAdminResponderThread.build2ColumnRow("Acceptor SubThread Active",
WebAdminResponderThread.WARNING_VALUE +
"Not Running" +
WebAdminResponderThread.WARNING_VALUE_END));
} // End of Else.
// ***********************************
// Check Responder Child Thread Status
if (this.responder != null) {
if (this.responder.isAlive()) {
sb.append(WebAdminResponderThread.build2ColumnRow("Responder SubThread Active",
WebAdminResponderThread.POSITIVE_VALUE +
Boolean.toString(this.responder.isAlive()) +
WebAdminResponderThread.POSITIVE_VALUE_END));
} else {
sb.append(WebAdminResponderThread.build2ColumnRow("Responder SubThread Active",
WebAdminResponderThread.CAUTION_VALUE +
Boolean.toString(this.responder.isAlive()) +
WebAdminResponderThread.CAUTION_VALUE_END));
} // End of Inner Else.
} else {
sb.append(WebAdminResponderThread.build2ColumnRow("Responder SubThread Active",
WebAdminResponderThread.WARNING_VALUE +
"Not Running" +
WebAdminResponderThread.WARNING_VALUE_END));
} // End of Else.
sb.append(WebAdminResponderThread.build2ColumnRow("Lap Time Message From Input Stack",
LP_ENTRY_FROM_COS.toString()));
sb.append(WebAdminResponderThread.build2ColumnRow("Lap Time Message To Output Stack",
LP_ENTRY_TO_COS.toString()));
// **************************************
// Finish our component status table.
sb.append(WebAdminResponderThread.END_TABLE);
// **************************************
// Return Formatted Status.
return sb.toString();
} // End of Protected GetStatus Method.
/**
* Helper Method to reset Component Statistics.
*/
protected void resetStatistics() {
// ***********************************************
// Initialize my LAP Timers
this.LP_ENTRY_TO_COS.Reset();
this.LP_ENTRY_FROM_COS.Reset();
} // End of resetStatistics protected method.
/**
* Private Initialization Method to Start Connection Acceptance and Responder
* threads.
*
* @throws Exception
*/
private void init() throws Exception {
Selector acceptSelector = Selector.open();
Selector readSelector = Selector.open();
WebAdminConnectionList connections = new WebAdminConnectionList(readSelector);
// **********************************
// Start Acceptor Thread.
acceptor = new WebAdminAcceptorThread(acceptSelector, connections,
this.WEBADMIN_PORT);
// **********************************
// Start Responder Thread.
responder = new WebAdminResponderThread(readSelector, connections,
this.CONTROL_THREAD,
this.cosin,
this.cosout,
this.WEBADMIN_ALLOW_LIST);
// ***************************
// Start these Threads.
this.responder.start();
this.acceptor.start();
} // End of private init method.
} ///:~ End of Class WebAdminServerThread