package jeffaschenk.commons.frameworks.cnxidx.resiliency.ldap; import java.util.*; import java.io.*; import jeffaschenk.commons.frameworks.cnxidx.utility.StopWatch; import jeffaschenk.commons.frameworks.cnxidx.utility.ldap.idxCMDReturnCodes; 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 org.jgroups.Address; import org.jgroups.JChannel; import org.jgroups.MembershipListener; import org.jgroups.Message; import org.jgroups.MessageListener; import org.jgroups.View; /** * Service Control Thread to perform Mainloop to Drive Log Restore Facilities. * In this Control Thread we perform the following: * - Setup the JGroups Channel * - Determine Responsibility * - Maintain Group Membership * - Boot Primary Replica Thread * - Boot Housecleaning Thread * - Boot Full Sync Thread, when needed. * * @author jeff.schenk * @version 4.4 $Revision * Developed 2005 */ public class IRRChangeLogRestoreServiceControlThread extends Thread implements MessageListener, MembershipListener, IRRChangeLogRestoreServiceVersion { // ******************************* // Common Logging Facility. private static final String CLASSNAME = IRRChangeLogRestoreServiceControlThread.class.getName(); private static final String THREAD_NAME = "ServiceControlThread"; // ******************************** // Default Multicast Address. private static final String DEFAULT_MULTICAST_ADDRESS_STRING = "224.0.0.35"; // ******************************** // Default Multicast Port. private static final String DEFAULT_MULTICAST_PORT_STRING = "45566"; // ******************************** // Default Group Name public static final String DEFAULT_GROUP_NAME = "ICOS-RESILIENCY-DIRECTORY-SYNC"; // ******************************* // Default JGroups Properties. private static final String DEFAULT_JGROUP_PROPERTY_STRING = "UDP(mcast_addr=224.0.0.35;mcast_port=45566;ip_ttl=32;" + "mcast_send_buf_size=150000;mcast_recv_buf_size=80000):" + "PING(timeout=2000;num_initial_members=3):" + "MERGE2(min_interval=5000;max_interval=10000):" + "FD_SOCK:" + "VERIFY_SUSPECT(timeout=1500):" + "pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800):" + "UNICAST(timeout=5000):" + "pbcast.STABLE(desired_avg_gossip=20000):" + "FRAG(frag_size=4096;down_thread=false;up_thread=false):" + "pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;" + "shun=false;print_local_addr=false)"; // ******************************* // JGroups Static Property Layers private static final String UDP_JGROUP_PROPERTY_STRING = "UDP(mcast_addr=%1;mcast_port=%2;ip_ttl=32;" + "mcast_send_buf_size=150000;mcast_recv_buf_size=80000):"; private static final String PING_JGROUP_PROPERTY_STRING = "PING(timeout=2000;num_initial_members=3):"; private static final String MERGE2_JGROUP_PROPERTY_STRING = "MERGE2(min_interval=5000;max_interval=10000):"; private static final String FD_JGROUP_PROPERTY_STRING = "FD_SOCK:"; private static final String VERIFY_JGROUP_PROPERTY_STRING = "VERIFY_SUSPECT(timeout=1500):"; private static final String PBCAST_NAKACK_JGROUP_PROPERTY_STRING = "pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800):"; private static final String UNICAST_JGROUP_PROPERTY_STRING = "UNICAST(timeout=5000):"; private static final String PBCAST_STABLE_JGROUP_PROPERTY_STRING = "pbcast.STABLE(desired_avg_gossip=20000):"; private static final String FRAG_JGROUP_PROPERTY_STRING = "FRAG(frag_size=4096;down_thread=false;up_thread=false):"; private static final String PBCAST_GMS_JGROUP_PROPERTY_STRING = "pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;" + "shun=false;print_local_addr=false)"; // ******************************* // JGroup Channel Objects private JChannel my_channel = null; //private PullPushAdapter my_adapter = null; private String my_mcast_address = null; private String my_mcast_port = null; private String my_group_name = null; private String my_property_string = null; // ******************************* // Memberships private boolean MULTIMASTER = false; // Experimental. private boolean PRIMARY_COORDINATOR = false; private Object PRIMARY_COORDINATOR_ADDR = null; protected List<Address> members = new ArrayList<>(); protected Object my_addr = null; // ******************************** // Global Indicators. private boolean READER_THREAD_READY = false; private boolean REPLICA_THREAD_READY = false; // ******************************* // Global Variables. private String IRRHost = null; private String IRRPrincipal = null; private String IRRCredentials = null; // private String INPUT_PATH = null; private String PUBLISH_EXCLUDE_DN_FILTER_FILE = null; private String RESTORE_EXCLUDE_DN_FILTER_FILE = null; // public static final int DEFAULT_WEBADMIN_PORT = 1389; protected int WEBADMIN_PORT = DEFAULT_WEBADMIN_PORT; // private String OPERATIONAL_MODE = null; public static final String DEFAULT_OPERATION_MODE = "DEFAULT"; // private LinkedList<String> WEBADMIN_ALLOW_LIST = null; public static final String DEFAULT_ALLOWABLE_HOST = "127.0.0.1"; // // ********************************** // ********************************** // Global TimeClocks. private StopWatch gsw = new StopWatch(); // ********************************** // Global Counters. private long FAILURE_COUNT = 0; private long stackcommands = 0; private long receivedstackcommands = 0; private long receivedinvalidobjects = 0; private long membershipupdatesreceived = 0; // *********************************** // Control counters used internally to // trigger housekeeping for PEER. private static final long DEFAULT_PEER_HOUSEKEEPING_THRESOLD = 128; private long replicacommands_issued = 0; // ******************************** // Thread Safe Global Stacks. private CircularObjectStack cos_control_common = null; private CircularObjectStack cos_control_to_changelog = null; private CircularObjectStack cos_control_to_replicarestore = null; private CircularObjectStack cos_publisher_common = null; private CircularObjectStack cos_control_to_webadmin = null; // ******************************** // Global Threads Maintained. private IRRChangeLogRestoreServiceReaderThread READER_THREAD = null; private IRRChangeLogRestoreServicePublisherThread PUBLISHER_THREAD = null; private IRRChangeLogRestoreServiceReplicaRestoreThread REPLICARESTORE_THREAD = null; private WebAdminServerThread WEBADMIN_THREAD = null; // ******************************** // Loop Timers. private final long BEGIN_WAIT_DURATION = (1000 * 2); // Start at 2 Seconds. private final long HIGH_WAIT_DURATION = (1000 * 300); // High Wait Duration is 5 Minutes. //private final long INCREMENTAL_WAIT_DURATION = (1000*30); // Increment at 30 Seconds. private long CURRENT_WAIT_DURATION = BEGIN_WAIT_DURATION; // ********************************* // Lap Timers. private idxLapTime LP_ENTRY_FROM_COS = new idxLapTime(); private idxLapTime LP_ENTRY_FROM_LOGDIR = new idxLapTime(); /** * IRRChangeLogRestoreServiceControlThread Contructor class driven from * Main or other Class Caller. */ public IRRChangeLogRestoreServiceControlThread(String IRRHost, String IRRPrincipal, String IRRCredentials, String INPUT_PATH, String PUBLISH_EXCLUDE_DN_FILTER_FILE, String RESTORE_EXCLUDE_DN_FILTER_FILE, int WEBADMIN_PORT, String OPERATIONAL_MODE) { this.IRRHost = IRRHost; this.IRRPrincipal = IRRPrincipal; this.IRRCredentials = IRRCredentials; this.INPUT_PATH = INPUT_PATH; this.PUBLISH_EXCLUDE_DN_FILTER_FILE = PUBLISH_EXCLUDE_DN_FILTER_FILE; this.RESTORE_EXCLUDE_DN_FILTER_FILE = RESTORE_EXCLUDE_DN_FILTER_FILE; this.WEBADMIN_PORT = WEBADMIN_PORT; this.OPERATIONAL_MODE = OPERATIONAL_MODE; // ************************************** // With this constructor we use the // Plain Default settings for our // Communications Properties. this.my_group_name = IRRChangeLogRestoreServiceControlThread.DEFAULT_GROUP_NAME; this.my_mcast_address = IRRChangeLogRestoreServiceControlThread.DEFAULT_MULTICAST_ADDRESS_STRING; this.my_mcast_port = IRRChangeLogRestoreServiceControlThread.DEFAULT_MULTICAST_PORT_STRING; // ***************************************** // Set our Default Allow List for WEBAdmin // Functionality. this.formulateWebAdminAllowList( IRRChangeLogRestoreServiceControlThread.DEFAULT_ALLOWABLE_HOST); // ************************************** // Name our Thread. this.setName(IRRChangeLogRestoreServiceControlThread.THREAD_NAME); } // End of Constructor for IRRChangeLogRestoreServiceControlThread. /** * IRRChangeLogRestoreServiceControlThread Contructor class driven from * Main or other Class Caller. */ public IRRChangeLogRestoreServiceControlThread(String IRRHost, String IRRPrincipal, String IRRCredentials, String INPUT_PATH, String PUBLISH_EXCLUDE_DN_FILTER_FILE, String RESTORE_EXCLUDE_DN_FILTER_FILE, int WEBADMIN_PORT, String OPERATIONAL_MODE, String GROUP_NAME, String MULTICAST_ADDRESS, String MULTICAST_PORT, String WEBADMIN_ALLOW_STRING) { this.IRRHost = IRRHost; this.IRRPrincipal = IRRPrincipal; this.IRRCredentials = IRRCredentials; this.INPUT_PATH = INPUT_PATH; this.PUBLISH_EXCLUDE_DN_FILTER_FILE = PUBLISH_EXCLUDE_DN_FILTER_FILE; this.RESTORE_EXCLUDE_DN_FILTER_FILE = RESTORE_EXCLUDE_DN_FILTER_FILE; this.WEBADMIN_PORT = WEBADMIN_PORT; this.OPERATIONAL_MODE = OPERATIONAL_MODE; // ****************************************** // With this constructor we use the overrides // for out Communications Properties. if ((GROUP_NAME == null) || (GROUP_NAME.trim().equalsIgnoreCase(""))) { this.my_group_name = IRRChangeLogRestoreServiceControlThread.DEFAULT_GROUP_NAME; } else { this.my_group_name = GROUP_NAME; } // End of Else. if ((MULTICAST_ADDRESS == null) || (MULTICAST_ADDRESS.trim().equalsIgnoreCase(""))) { this.my_mcast_address = IRRChangeLogRestoreServiceControlThread.DEFAULT_MULTICAST_ADDRESS_STRING; } else { this.my_mcast_address = MULTICAST_ADDRESS; } // End of Else. if ((MULTICAST_PORT == null) || (MULTICAST_PORT.trim().equalsIgnoreCase(""))) { this.my_mcast_port = IRRChangeLogRestoreServiceControlThread.DEFAULT_MULTICAST_PORT_STRING; } else { try { Integer.parseInt(MULTICAST_PORT); this.my_mcast_port = MULTICAST_PORT; } catch (NumberFormatException nfe) { this.my_mcast_port = IRRChangeLogRestoreServiceControlThread.DEFAULT_MULTICAST_PORT_STRING; } // End of Exception processing. } // End of Else. // ********************************************** // Now determine if there is anything additional // Address I need to pick up. if ((WEBADMIN_ALLOW_STRING != null) && (!WEBADMIN_ALLOW_STRING.trim().equalsIgnoreCase(""))) { this.formulateWebAdminAllowList(WEBADMIN_ALLOW_STRING); } else { // ***************************************** // Set our Default Allow List for WEBAdmin // Functionality. this.formulateWebAdminAllowList( IRRChangeLogRestoreServiceControlThread.DEFAULT_ALLOWABLE_HOST); } // End of Else. // ************************************** // Name our Thread. this.setName(IRRChangeLogRestoreServiceControlThread.THREAD_NAME); } // End of Constructor for IRRChangeLogRestoreServiceControlThread. /** * Service Control Thread */ public void run() { final String METHODNAME = "run"; gsw.start(); // Start our Global Time Clock for our Duration. // ************************************************* // Boot Service Control Thread. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.BOOT); // ************************************************* // Check Requested Operational Mode. if ((this.OPERATIONAL_MODE == null) || (this.OPERATIONAL_MODE.equalsIgnoreCase(""))) { this.OPERATIONAL_MODE = IRRChangeLogRestoreServiceControlThread.DEFAULT_OPERATION_MODE; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_REQUESTED_DEFAULT_OPERATIONAL_MODE); } else { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_REQUESTED_OPERATIONAL_MODE, new String[]{this.OPERATIONAL_MODE}); } // End of Else. // ************************************************* // TODO // Determine if this is a restart from a failure? // Meaning, did we or our machine fail, if that is // the case a new PRIMARY Coordinator should have been // picked. // FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.DETERMINE_PRIOR_STATE); FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.PRIOR_STATE_UNKNOWN); // ************************************************** // Establish our Synchronized Circular Stack Objects // used for Threads queues to drive work in other // threads. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.INITIALIZING_STACKS); this.cos_control_common = new CircularObjectStack(); this.cos_control_to_changelog = new CircularObjectStack(); this.cos_publisher_common = new CircularObjectStack(); this.cos_control_to_replicarestore = new CircularObjectStack(); this.cos_control_to_webadmin = new CircularObjectStack(); FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.STACKS_INITIALIZED); // ************************************************ // Set up our JGroups Channel Communications. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.INITIALIZING_RESILIENCY_COMMUNICATION_LAYER); try { // ***************************** // Show our Group Name. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.RESILIENCY_MEMBERSHIP_NAME, new String[]{this.my_group_name}); // ********************************* // Build JGroups Property String. this.my_property_string = this.formulateJGroupsProperties(); // ********************************* // Show our JGroups Property // String. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.RESILIENCY_PROPERTIES, new String[]{this.my_property_string}); // ***************************** // Start JavaGroups. this.startJGroups(); } catch (Exception e) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.SEVERE, ErrorConstants.COMMUNICATION_EXCEPTION, new String[]{e.toString()}); this.logStackTrace(e, METHODNAME, ErrorConstants.COMMUNICATION_EXCEPTION_STACKTRACE); System.exit(idxCMDReturnCodes.EXIT_GENERIC_FAILURE); } // End of Exception Processing. // ************************************************** // Show JGroups Open Successfully. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.RESILIENCY_COMMUNICATIONS_LAYER_INITIALIZED, new String[]{this.my_addr.toString()}); // ************************************************** // Start the Common Publisher Service Thread. // FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.STARTING_PUBLISHER_THREAD); this.startPublisherThread(); this.publishEcho(); // Send out an Echo. // ************************************************** // Start the Change Log Queue Service. // This is used when this instance // is a Primary Coordinator. // FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.STARTING_READER_THREAD); this.startReaderThread(); // ************************************************** // Start the Replica Restore Service Thread. // FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.STARTING_REPLICARESTORE_THREAD); this.startReplicaRestoreThread(); // *********************************************** // Start the Web Admin Service Thread. // FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.STARTING_WEBADMIN_THREAD); this.startWebAdminThread(); // *********************************************** // Indicate Boot Sequence is complete. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.BOOT_SEQUENCE_COMPLETE); // *********************************************** // Initialize and Main Thread Loop Variables. StackCommand instackcommand = null; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.STARTING_MAIN_CONTROL_THREAD_LOOP); // ********************************************* // Perform our Main Thread Loop until // the Thread is interrupted // at Shutdown request Time. // boolean control_running = true; try { while (control_running) { // ****************************** // Determine if anything is on // the common control stack. instackcommand = null; // Be sure to Clear Previous Entry. LP_ENTRY_FROM_COS.Start(); if (this.cos_control_common.hasMoreNodes()) { instackcommand = (StackCommand) this.cos_control_common.getNext(); } LP_ENTRY_FROM_COS.Stop(); // *************************** // Did anything get pulled // from stack? if (instackcommand != null) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.CONTROL_STACK_COMMAND_POPPED, new String[]{instackcommand.toString()}); this.stackcommands++; // *************************** // Interpret the Stack Command switch (instackcommand.getCommandType()) { case StackCommand.CL_END_OF_THREAD: break; // ************************************* // Process Echo Command. case StackCommand.CL_ECHO: // ****************************** // We basically turn this object // into a reply hence the echo // and place on JGroups Publisher // Queue at the bottom of the queue. instackcommand.setCommandType(StackCommand.CL_ECHO_REPLY); this.cos_publisher_common.push(instackcommand); break; // ************************************* // Process Echo Reply Command. case StackCommand.CL_ECHO_REPLY: if (instackcommand.getObject() != null) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_STACK_ECHO_REPLY, new String[]{instackcommand.getObject().toString()}); } else { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_STACK_ECHO_REPLY_WITH_EMPTY_OBJECT); } // End of Else. break; // ************************************* // Process Remote Status Command for // PEERS other than us and we may get // a status call from ourselves as well. case StackCommand.CL_STATUS: this.processRemoteStatusCommand(instackcommand); break; // ************************************* // Reader Thread has indicated it is // ready. case StackCommand.CL_READER_READY: this.READER_THREAD_READY = true; break; // ************************************* // Reader Thread has indicated it is // ready. case StackCommand.CL_REPLICA_READY: this.REPLICA_THREAD_READY = true; break; // ************************************* // Process Start of Reader Thread. // Only start if we really need to. case StackCommand.CL_START_READER: if ((this.READER_THREAD == null) || (!this.READER_THREAD.t.isAlive())) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.CONTROL_REQUEST_TO_START_READER_ACCEPTED); this.startReaderThread(); } else { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.CONTROL_REQUEST_TO_START_READER_IGNORED); } // End of Else. break; // ************************************* // Process Stop of Reader Thread. // Only start if we really need to. case StackCommand.CL_STOP_READER: if ((this.READER_THREAD != null) && (this.READER_THREAD.t.isAlive())) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.CONTROL_REQUEST_TO_STOP_READER_ACCEPTED); this.stopReaderThread(); } else { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.CONTROL_REQUEST_TO_STOP_READER_IGNORED); } // End of Else. this.READER_THREAD_READY = false; break; // ************************************* // Process Start of Reader Thread. // Only start if we really need to. case StackCommand.CL_START_REPLICA: if ((this.REPLICARESTORE_THREAD == null) || (!this.REPLICARESTORE_THREAD.t.isAlive())) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.CONTROL_REQUEST_TO_START_REPLICA_ACCEPTED); this.startReplicaRestoreThread(); } else { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.CONTROL_REQUEST_TO_START_REPLICA_IGNORED); } // End of Else. break; // ************************************* // Process Stop of Reader Thread. // Only start if we really need to. case StackCommand.CL_STOP_REPLICA: if ((this.REPLICARESTORE_THREAD != null) && (this.REPLICARESTORE_THREAD.t.isAlive())) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.CONTROL_REQUEST_TO_STOP_READER_ACCEPTED); this.stopReplicaRestoreThread(); } else { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.CONTROL_REQUEST_TO_STOP_READER_IGNORED); } // End of Else. this.REPLICA_THREAD_READY = false; break; // ************************************* // Process a Reset of all Statistics. case StackCommand.CL_RESET_STATS: this.resetStatistics(); break; // ************************************** // Process any Housekeeping Completions. case StackCommand.CL_HOUSEKEEPING_DONE: if (instackcommand.getObject() != null) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_HOUSEKEEPING_COMPLETED_WITH_FILES_PURGED, new String[]{((Long) instackcommand.getObject()).toString()}); } // End of Null check for any Counts. else { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_HOUSEKEEPING_COMPLETED); } // End of Else. break; // ************************************* // Process other Control State Commands // when Necessary. case StackCommand.CL_PRIMARY: case StackCommand.CL_WAS_PRIMARY: case StackCommand.CL_PEER: break; // ************************************** // Ok, did someone request shutdown, if so // perform it. case StackCommand.CL_SHUTDOWN: control_running = false; break; // **************************** // Ignore Any unknown Commands. default: FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.IGNORED_UNKNOWN_COMMAND); } // End of Switch Statement. } // End of Check for Null or no Stack Command. // ************************************ // If we received a Shutdown command, // then force our thread into shutdown // processing before we do anything else. if (!control_running) { break; } // Break out of our Main While Loop. // *********************************** // Only if we are Primary or MM will // we perform the Following // to check for Change // Logs and place those in the // Stack to be processed by our Reader. // The Reader must be Ready to // receive and there must at least // another Member in our Group. if (((this.PRIMARY_COORDINATOR) || (this.MULTIMASTER)) && (this.READER_THREAD_READY) && (this.members.size() > 1)) { // **************************************** // Obtain a Directory Listing of all // unProcessed Files in time order. LP_ENTRY_FROM_LOGDIR.Start(); TreeMap upf = IRRChangeLogFileUtility.obtainUnprocessedFileMap( this.INPUT_PATH); LP_ENTRY_FROM_LOGDIR.Stop(); // ***************************************** // Now Send Command to our Reader Thread // to Process the Change Logs. if ((upf != null) && (!upf.isEmpty())) { this.cos_control_to_changelog.push( new StackCommand(StackCommand.CL_PROCESS_LOGS, this.my_addr, upf)); FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_PLACING_LOGS_TO_BE_PROCESSED_ON_STACK, new String[]{Integer.toString(upf.size())}); // ************************************* // Indicate the Thread will need to ask // when it is ready. this.READER_THREAD_READY = false; } // End of Queuing files to be processed. } // End of primary or MultiMaster Check. // ******************************************** // Determine if we are not Primary, just a // simple PEER, then we need to Trigger // some housekeeping when our threshold // has been met. else if (((!this.PRIMARY_COORDINATOR) && (!this.MULTIMASTER)) && (this.READER_THREAD_READY) && (this.members.size() > 1) && (DEFAULT_PEER_HOUSEKEEPING_THRESOLD <= this.replicacommands_issued)) { this.cos_control_to_changelog.push( new StackCommand(StackCommand.CL_HOUSEKEEPING_BEGIN_PEER, this.my_addr)); FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_TRIGGERING_HOUSEKEEPING_FOR_PEER); this.replicacommands_issued = 0; } // End of Check for PEER. // *************************** // Did we process anything? if (instackcommand == null) { // *************************** // Wait for a Tick or two. // Reset if we reached our max // wait interval. if (CURRENT_WAIT_DURATION > HIGH_WAIT_DURATION) { CURRENT_WAIT_DURATION = BEGIN_WAIT_DURATION; } Thread.sleep(CURRENT_WAIT_DURATION); } // End of Nothing in Stack yet to Process. } // End of While Loop. } catch (InterruptedException e) { control_running = false; } finally { this.shutdown(); } // End of Final Processing Block. } // End of Thread Execution run. /* ------------------------------------------------------------ */ /* MembershipListener Interface */ /* Handler Callbacks and Implementation Methods */ /* ------------------------------------------------------------ */ public void viewAccepted(View view) { this.setMembershipState(view.getMembers()); } public void suspect(Address suspected_mbr) { } public void block() { } @Override public void unblock() { // TODO -- } @Override public void getState(OutputStream outputStream) throws Exception { } @Override public void setState(InputStream inputStream) throws Exception { } /* ------------------------------------------------------------ */ /* MessageListener Interface */ /* Handler Callbacks and Implementation Methods */ /* ------------------------------------------------------------ */ /** * Callback method to handle all Message Receives. * We will determine which thread to direct this object to * based upon Object Instance type. * * @param msg Message Received. */ public void receive(Message msg) { // ************************************** // Initialize final String METHODNAME = "receive"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); Object o; try { o = msg.getObject(); if (!(o instanceof StackCommand)) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.CONTROL_RECEIVED_UNKNOWN_MESSAGE_TYPE, new String[]{msg.getSrc().toString(), o.getClass().getName(), o.toString()}); this.receivedinvalidobjects++; return; } // End of If. // ***************************** // Now we have a StackCommand // received, determine what to do // with it based upon request. StackCommand instackcommand = (StackCommand) o; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_RECEIVED_MESSAGE, new String[]{msg.getSrc().toString(), instackcommand.toString()}); this.receivedstackcommands++; // ************************************ // Dispatch command to correct stack. switch (instackcommand.getCommandType()) { // **************************** // Control State Stack Commands. case StackCommand.CL_STATUS: case StackCommand.CL_ECHO: case StackCommand.CL_ECHO_REPLY: case StackCommand.CL_PRIMARY: case StackCommand.CL_WAS_PRIMARY: case StackCommand.CL_PEER: // ************************************ // Place Object on Control Stack. this.cos_control_common.push(instackcommand); break; // *********************************************** // Ensure we were the destination or destination // address is null, if so pass on the Shutdown. case StackCommand.CL_SHUTDOWN: if ((instackcommand.getDestination() == null) || (instackcommand.getDestination().equals(this.my_addr))) { this.cos_control_common.push(instackcommand); } break; // ************************************************ // Check for a Global Reset of Stats or for just // this instance. case StackCommand.CL_RESET_STATS: if ((instackcommand.getDestination() == null) || (instackcommand.getDestination().equals(this.my_addr))) { this.cos_control_common.push(instackcommand); } break; // ***************************************** // Ensure we were the destination, if not // Ignore the command. case StackCommand.CL_START_READER: case StackCommand.CL_STOP_READER: case StackCommand.CL_START_REPLICA: case StackCommand.CL_STOP_REPLICA: case StackCommand.CL_HOUSEKEEPING_BEGIN_PRIMARY: case StackCommand.CL_HOUSEKEEPING_BEGIN_PEER: if ((instackcommand.getDestination() != null) && (instackcommand.getDestination().equals(this.my_addr))) { this.cos_control_common.push(instackcommand); } break; // ***************************************** // Ensure we were the originator, if not // Ignore the command. case StackCommand.CL_READER_READY: case StackCommand.CL_REPLICA_READY: case StackCommand.CL_HOUSEKEEPING_READY: case StackCommand.CL_HOUSEKEEPING_DONE: if (instackcommand.getOriginator().equals(this.my_addr)) { this.cos_control_common.push(instackcommand); } break; // ******************************* // WEB Admin Status Reply Commands. case StackCommand.CL_STATUS_REPLY: // ************************************ // Place Object on WebAdmin Stack if we // are the destination, otherwise we could // trash our local queue. // if (instackcommand.getDestination().equals(this.my_addr)) { this.cos_control_to_webadmin.push(instackcommand); } break; // ***************************** // Replica Restore Commands. case StackCommand.CL_REPLICATE: if (((!this.PRIMARY_COORDINATOR)) || ((this.MULTIMASTER) && (!instackcommand.getOriginator().equals(this.my_addr)))) { // ************************************ // Place Object on Control Stack. this.cos_control_to_replicarestore.push(instackcommand); // ************************************ // Increment our counter to trigger // of clean up on the PEER Input Path // otherwise we could have lots of // unnecessary duplicated changes. this.replicacommands_issued++; // ************************************ // Make sure our replica if (!this.REPLICA_THREAD_READY) { // ********************************************* // Indicate Replica is not Ready and Queue // Building. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.REPLICA_RESTORE_THREAD_NOT_READY_QUEUE_BUILDING, new String[]{Integer.toString(this.cos_control_to_replicarestore.size())}); } // End of Checking for Replica Thread is Ready. } // End of Check, only perform if not Primary not MM. else { // ********************************************** // Produce Information Message indicating we are // dropping a Replica Request. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.CONTROL_DROPPING_REPLICA_RESTORE_REQUEST, new String[]{instackcommand.getOriginator().toString()}); } // End of Else. break; // ***************************** // Replica Restore Commands. case StackCommand.CL_REPLICATE_RESPONSE: // ************************************ // Ensure this Response did not come // from us, if so ignore. if (!instackcommand.getOriginator().equals(this.my_addr)) { // ************************************ // Place Object on Control Stack to be sent to // Reader. this.cos_control_to_changelog.push(instackcommand); } // End of If Check. else { // ********************************************** // Produce Information Message indicating we are // dropping a Replica Response. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.CONTROL_DROPPING_REPLICA_RESPONSE, new String[]{instackcommand.getOriginator().toString()}); } // End of Else. break; // ****************************** // Log Reader Commands. case StackCommand.CL_MARK_POINT: case StackCommand.CL_MARK_AS_PROCESSED: case StackCommand.CL_REMOVE_MARK_POINT: case StackCommand.CL_REMOVE_LOG: // ************************************ // Place Object on Control Stack. this.cos_control_common.push(instackcommand); break; // ********************************* // Default Ignore the Received. default: FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.WARNING, MessageConstants.IGNORED_UNKNOWN_COMMAND); } // End of Switch Statement. } catch (Exception e) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.SEVERE, ErrorConstants.COMMUNICATION_RECEIVE_EXCEPTION, new String[]{e.toString()}); } // End of Exception Processing. } // End of receive method. /* ------------------------------------------------------------ */ /* Protected Methods */ /* ------------------------------------------------------------ */ /** * Helper Method to obtain Status from all Components and * send status back to WEB Admin to respond to a user * requesting status. */ protected String obtainLocalStatus(boolean forremote) { final String METHODNAME = "obtainLocalStatus"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); StringBuffer sb = new StringBuffer(); // ******************************** // Now Obtain Status from other // Components. sb.append(WebAdminResponderThread.BEGIN_TABLE); sb.append(WebAdminResponderThread.BEGIN_ROW); sb.append(WebAdminResponderThread.BEGIN_COL); sb.append(this.getStatus()); sb.append(WebAdminResponderThread.END_COL); sb.append(WebAdminResponderThread.BEGIN_COL); sb.append(this.PUBLISHER_THREAD.getStatus()); sb.append(this.WEBADMIN_THREAD.getStatus()); sb.append(WebAdminResponderThread.END_COL); sb.append(WebAdminResponderThread.END_ROW); sb.append(WebAdminResponderThread.BEGIN_ROW); sb.append(WebAdminResponderThread.BEGIN_COL); // ******************************************** // Now Verify Reader Thread is Running. if ((this.READER_THREAD == null) || (!this.READER_THREAD.t.isAlive())) { sb.append(IRRChangeLogRestoreServiceReaderThread.getOfflineStatus()); } else { sb.append(this.READER_THREAD.getStatus()); } sb.append(WebAdminResponderThread.END_COL); sb.append(WebAdminResponderThread.BEGIN_COL); // ********************************************* // Now Verify Replica Restore Thread is Running. if ((this.REPLICARESTORE_THREAD == null) || (!this.REPLICARESTORE_THREAD.t.isAlive())) { sb.append(IRRChangeLogRestoreServiceReplicaRestoreThread.getOfflineStatus()); } else { sb.append(this.REPLICARESTORE_THREAD.getStatus()); } // *************************************** // Finish up Table. sb.append(WebAdminResponderThread.END_COL); sb.append(WebAdminResponderThread.END_ROW); sb.append(WebAdminResponderThread.END_TABLE); // ****************************** // return Response String. return sb.toString(); } // End of getStatus Method. /** * Helper Method to reset all Component Statistics. */ protected void resetStatistics() { final String METHODNAME = "resetStatistics"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // ******************************** // Reset this Thread Statistics this.FAILURE_COUNT = 0; this.stackcommands = 0; this.receivedstackcommands = 0; this.receivedinvalidobjects = 0; this.membershipupdatesreceived = 0; this.LP_ENTRY_FROM_COS.Reset(); this.LP_ENTRY_FROM_LOGDIR.Reset(); // ********************************* // Reset Publisher Statistics this.PUBLISHER_THREAD.resetStatistics(); // ********************************* // Reset WebAdmin Statistics this.WEBADMIN_THREAD.resetStatistics(); // ******************************************** // Now Verify Reader Thread is Running, // if so, reset it's stats. if ((this.READER_THREAD != null) && (this.READER_THREAD.t.isAlive())) { this.READER_THREAD.resetStatistics(); } // ********************************************* // Now Verify Replica Restore Thread is Running. if ((this.REPLICARESTORE_THREAD != null) && (this.REPLICARESTORE_THREAD.t.isAlive())) { this.REPLICARESTORE_THREAD.resetStatistics(); } } // End of resetStatistics Method. /* ------------------------------------------------------------ */ /* Private Methods */ /* ------------------------------------------------------------ */ /** * Helper Method to obtain Status from all Components and * send status back to respond to a remote request. */ private void processRemoteStatusCommand(StackCommand statuscommand) { final String METHODNAME = "processRemoteStatusCommand"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // *********************************** // Check for NULL StackCommand Object. if (statuscommand == null) { return; } // ********************************** // Flip the Command Type to Reply and // place our Status into the Stack // Command Wrapper. statuscommand.setCommandType(StackCommand.CL_STATUS_REPLY); statuscommand.setObject(this.obtainLocalStatus(true)); statuscommand.setDestination(statuscommand.getOriginator()); statuscommand.setOriginator(this.my_addr); this.cos_publisher_common.push(statuscommand); } // End of processRemoteStatusCommand Method. /** * Helper method to provide current determination of * the Membership state and who is the Primary Coordinator. * If we are not Primary Coordinator, then we become a * slave and anything received will be replicated to our local * Directory Instance. * * @param mbrs Vector Object containing current Members. */ private void setMembershipState(List<Address> mbrs) { // ********************************* // Initialize. final String METHODNAME = "setmembershipState"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); this.membershipupdatesreceived++; // ******************************** // Save new List of Members. members.removeAll(members); for (int i = 0; i < mbrs.size(); i++) { members.add(mbrs.get(i)); } // ****************************************** // Now Determine who is Primary Coordinator. if (mbrs.size() <= 1 || (mbrs.size() > 1 && mbrs.get(0).equals(my_addr))) { if (this.PRIMARY_COORDINATOR_ADDR == null) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_INITIALIZED_AS_PRIMARY_COORDINATOR, new String[]{this.my_addr.toString()}); } else if (this.PRIMARY_COORDINATOR_ADDR.equals(my_addr)) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_MAINTAINING_STATE_AS_PRIMARY_COORDINATOR, new String[]{this.my_addr.toString()}); } else { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_STATE_CHANGE, new String[]{this.my_addr.toString(), this.PRIMARY_COORDINATOR_ADDR.toString()}); } // End of Inner Else. // **************************** // Establish As Primary. this.PRIMARY_COORDINATOR_ADDR = this.my_addr; // We are now the Primary. this.PRIMARY_COORDINATOR = true; } else { this.PRIMARY_COORDINATOR = false; if (mbrs.size() > 0) { this.PRIMARY_COORDINATOR_ADDR = mbrs.get(0); FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_NOT_PRIMARY_COORDINATOR, new String[]{this.PRIMARY_COORDINATOR_ADDR.toString()}); } else { this.PRIMARY_COORDINATOR_ADDR = null; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.SEVERE, MessageConstants.CONTROL_NO_PRIMARY_COORDINATOR); } // End of Else. } // End of Outer Else. } // End of setMembershipState. /** * Provide convience method to start Publisher Thread. */ private void startPublisherThread() { final String METHODNAME = "startPublisherThread"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // ************************************************** // Start the Common Publisher Service Thread. // PUBLISHER_THREAD = new IRRChangeLogRestoreServicePublisherThread( this.my_channel, this.cos_publisher_common); // ****************************************** // Check for the Publisher Thread // to be running... // if (PUBLISHER_THREAD.t.isAlive()) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_PUBLISHER_THREAD_RUNNING); } else { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.SEVERE, MessageConstants.CONTROL_PUBLISHER_THREAD_NOT_RUNNING); } // End of Else. } // End of startPublisherThread /** * Provide convience method to stop Publisher Thread. */ private void stopPublisherThread() { final String METHODNAME = "stopPublisherThread"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // ************************************************** // Stop the Common Publisher Service Thread. // Indicate to my Publisher Thread // to End Thread. this.cos_publisher_common.push( new StackCommand(StackCommand.CL_END_OF_THREAD, this.my_addr)); // ******************************************* // Now Join the Reader Thread. try { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_PUBLISHER_THREAD_WATING_TO_COMPLETE); PUBLISHER_THREAD.t.join(); } catch (InterruptedException e) { } // End of Exception. // **************************** // Thread Stopped. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_PUBLISHER_THREAD_STOPPED); } // End of stopPublisherThread /** * Provide convience method to Send an Echo Command to our Publisher Thread. */ private void publishEcho() { final String METHODNAME = "publishEcho"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // ************************************************** // Stop the Common Publisher Service Thread. // Indicate to my Publisher Thread // to End Thread. this.cos_publisher_common.push( new StackCommand(StackCommand.CL_ECHO, this.my_addr)); } // End of publishEcho /** * Provide convience method to start Publisher Thread. */ private void startReaderThread() { final String METHODNAME = "startReaderThread"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // ************************************************** // Check before we do something stupid. if ((this.READER_THREAD != null) && (this.READER_THREAD.t.isAlive())) { return; } // ************************************************** // Start the Change Log Queue Service. // This is used when this instance // is a Primary Coordinator. // READER_THREAD = new IRRChangeLogRestoreServiceReaderThread( this, this.cos_control_to_changelog, this.cos_publisher_common, this.INPUT_PATH, this.PUBLISH_EXCLUDE_DN_FILTER_FILE); // ****************************************** // Check for the Reader Thread // to be running... // if (READER_THREAD.t.isAlive()) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_READER_THREAD_RUNNING); } else { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.SEVERE, MessageConstants.CONTROL_READER_THREAD_NOT_RUNNING); } // End of Else. } // End of startReaderThread. /** * Provide convience method to stop Reader Thread. */ private void stopReaderThread() { final String METHODNAME = "stopReaderThread"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // ************************************************** // Check before we do something stupid. if ((this.READER_THREAD == null) || (!this.READER_THREAD.t.isAlive())) { return; } // ************************************************** // Stop the Reader Service Thread. // Indicate to my Reader Thread // to End Thread. this.cos_control_to_changelog.push( new StackCommand(StackCommand.CL_END_OF_THREAD, this.my_addr)); // ******************************************* // Now Join the Reader Thread. try { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_READER_THREAD_WATING_TO_COMPLETE); this.READER_THREAD.t.join(); } catch (InterruptedException e) { } // End of Exception. // **************************** // Thread Stopped. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_READER_THREAD_STOPPED); this.READER_THREAD = null; } // End of stopReaderThread /** * Provide convience method to start Replica Restore Thread. */ private void startReplicaRestoreThread() { final String METHODNAME = "startReplicaRestoreThread"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // ************************************************** // Check before we do something stupid. if ((this.REPLICARESTORE_THREAD != null) && (this.REPLICARESTORE_THREAD.t.isAlive())) { return; } // ************************************************** // Start the Common Publisher Service Thread. // REPLICARESTORE_THREAD = new IRRChangeLogRestoreServiceReplicaRestoreThread( this, this.cos_control_to_replicarestore, this.cos_publisher_common, this.IRRHost, this.IRRPrincipal, this.IRRCredentials, this.RESTORE_EXCLUDE_DN_FILTER_FILE); // ****************************************** // Check for the Reader Thread // to be running... // if (REPLICARESTORE_THREAD.t.isAlive()) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_REPLICARESTORE_THREAD_RUNNING); } else { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.SEVERE, MessageConstants.CONTROL_REPLICARESTORE_THREAD_NOT_RUNNING); } // End of Else. } // End of startReplicaRestoreThread. /** * Provide convience method to stop Replica Restore Thread. */ private void stopReplicaRestoreThread() { final String METHODNAME = "stopReplicaRestoreThread"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // ************************************************** // Check before we do something stupid. if ((this.REPLICARESTORE_THREAD == null) || (!this.REPLICARESTORE_THREAD.t.isAlive())) { return; } // ************************************************** // Stop the Replica Restore Service Thread. // Indicate to my Reader Thread // to End Thread. this.cos_control_to_replicarestore.push( new StackCommand(StackCommand.CL_END_OF_THREAD, this.my_addr)); // ******************************************* // Now Join the Replica Restore Thread. try { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_REPLICARESTORE_THREAD_WATING_TO_COMPLETE); this.REPLICARESTORE_THREAD.t.join(); } catch (InterruptedException e) { } // End of Exception. // **************************** // Thread Stopped. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_REPLICARESTORE_THREAD_STOPPED); this.REPLICARESTORE_THREAD = null; } // End of stopReplicaRestoreThread. /** * Provide convience method to start Publisher Thread. */ private void startWebAdminThread() { final String METHODNAME = "startWebAdminThread"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // ************************************************** // Verify we have a valid Web Admin Port. if (this.WEBADMIN_PORT < DEFAULT_WEBADMIN_PORT) { this.WEBADMIN_PORT = DEFAULT_WEBADMIN_PORT; } // ************************************************** // Start the Change Log Queue Service. // This is used when this instance // is a Primary Coordinator. // WEBADMIN_THREAD = new WebAdminServerThread(this, this.cos_control_to_webadmin, this.cos_publisher_common, this.WEBADMIN_PORT, this.WEBADMIN_ALLOW_LIST); // ****************************************** // Check for the Reader Thread // to be running... // if (WEBADMIN_THREAD.t.isAlive()) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_WEBADMIN_THREAD_RUNNING); } else { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.SEVERE, MessageConstants.CONTROL_WEBADMIN_THREAD_NOT_RUNNING); } // End of Else. } // End of startWebAdminThread. /** * Provide convience method to stop Reader Thread. */ private void stopWebAdminThread() { final String METHODNAME = "stopWebAdminThread"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // ************************************************** // Stop the Reader Service Thread. // Indicate to my Reader Thread // to End Thread. this.cos_control_to_webadmin.push( new StackCommand(StackCommand.CL_END_OF_THREAD, this.my_addr)); // ******************************************* // Now Join the Reader Thread. try { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_WEBADMIN_THREAD_WATING_TO_COMPLETE); WEBADMIN_THREAD.t.join(); } catch (InterruptedException e) { } // End of Exception. // **************************** // Thread Stopped. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_WEBADMIN_THREAD_STOPPED); } // End of stopWebAdminThread /** * startJGroups convience method to instantiate our * Channel Membership. */ private void startJGroups() throws Exception { final String METHODNAME = "startJGroups"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // ********************************** // Create the Channel. my_channel = new JChannel(my_property_string); //my_channel.setOpt(Channel.AUTO_RECONNECT, Boolean.TRUE); // ********************************** // Connect to Channel Membership. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_CONNECTING_TO_GROUP, new String[]{this.my_group_name}); my_channel.connect(my_group_name); my_addr = my_channel.getAddress(); // *********************************** // Instantiate Adapter to establish // Listeners. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_ESTABLISHING_ADAPTER); //my_adapter = new PullPushAdapter(my_channel, this, this); } // End of startJGroups. /** * Helper method to formulate the JGroups Property String. * * @return String Forumlated JGroups Property String. */ private String formulateJGroupsProperties() { StringBuffer sb = new StringBuffer(); // ***************************** // Initialize with UDP Layer. sb.append(IRRChangeLogRestoreServiceControlThread.UDP_JGROUP_PROPERTY_STRING); // ***************************** // Zap in the Multicast Address int i = sb.indexOf("%1"); if (i > 0) { sb.replace(i, (i + 2), this.my_mcast_address); } // End of Multicast Address Zap. else { return IRRChangeLogRestoreServiceControlThread.DEFAULT_JGROUP_PROPERTY_STRING; } // end of Else. // ***************************** // Zap in the MultiCast Port. i = sb.indexOf("%2"); if (i > 0) { sb.replace(i, (i + 2), this.my_mcast_port); } // End of Multicast Address Zap. else { return IRRChangeLogRestoreServiceControlThread.DEFAULT_JGROUP_PROPERTY_STRING; } // end of Else. // ***************************** // Set up Remaining Layers sb.append(IRRChangeLogRestoreServiceControlThread.PING_JGROUP_PROPERTY_STRING); sb.append(IRRChangeLogRestoreServiceControlThread.MERGE2_JGROUP_PROPERTY_STRING); sb.append(IRRChangeLogRestoreServiceControlThread.FD_JGROUP_PROPERTY_STRING); sb.append(IRRChangeLogRestoreServiceControlThread.VERIFY_JGROUP_PROPERTY_STRING); sb.append(IRRChangeLogRestoreServiceControlThread.PBCAST_NAKACK_JGROUP_PROPERTY_STRING); sb.append(IRRChangeLogRestoreServiceControlThread.UNICAST_JGROUP_PROPERTY_STRING); sb.append(IRRChangeLogRestoreServiceControlThread.PBCAST_STABLE_JGROUP_PROPERTY_STRING); sb.append(IRRChangeLogRestoreServiceControlThread.FRAG_JGROUP_PROPERTY_STRING); sb.append(IRRChangeLogRestoreServiceControlThread.PBCAST_GMS_JGROUP_PROPERTY_STRING); // ***************************** // Return Formulated String. return sb.toString(); } // End of formulateJGroupsProperties private Method. /** * Formulate a List from a String seperated by commas. * * @param str */ private void formulateWebAdminAllowList(String str) { final String METHODNAME = "formulateWebAdminAllowList"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // ******************************** // Initialize our Allow List. this.WEBADMIN_ALLOW_LIST = new LinkedList<>(); // ******************************** // Ensure we have something in the // String. if ((str == null) || (str.trim().equalsIgnoreCase(""))) { return; } // ******************************** // Process each Element. String[] elements = str.split("\\,"); for (int i = 0; i < elements.length; i++) { if ((elements[i] != null) && (!elements[i].trim().equalsIgnoreCase(""))) { FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.CONTROL_ADDING_WEBADMIN_ALLOWABLE_ADDRESS, new String[]{elements[i]}); this.WEBADMIN_ALLOW_LIST.add(elements[i]); } // End of Inner If Check for Valid Element. } // End of For Loop. } // End of formulateWebAdminAllowList private Method. /** * Private Shutdown Method to wrap all * final processing. */ private void shutdown() { final String METHODNAME = "shutdown"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); // ********************************* // Perform Clean-up to ready for // Shutdown. FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.SHUTDOWN_STARTED); // ********************************** // Stop All Threads, gracefully. this.stopReplicaRestoreThread(); this.stopReaderThread(); this.stopPublisherThread(); this.stopWebAdminThread(); // *********************************** // Now Stop our Adapter. //this.my_adapter.stop(); // *********************************************** // notify controller thread that we have finished synchronized (this) { notify(); } // End of Synchronized Code Area. // ************************************* // Perform Final Message Indication for // Shutdown. gsw.stop(); FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.INFO, MessageConstants.SHUTDOWN_COMPLETED, new String[]{gsw.getElapsedTimeString()}); } // End of shutdown private method. /** * Get Current Component Status. * * @return String Data Representing Current Status of this Component. */ private String getStatus() { // ************************************** // Initialize. final String METHODNAME = "getStatus"; FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.DEBUG, MessageConstants.ENTERING_CONTROL_METHOD, new String[]{METHODNAME}); StringBuffer sb = new StringBuffer(); // ************************************** // Build String Buffer with Status for // this component. // ************************************** // Show Header sb.append(WebAdminResponderThread.COMPONENT_BEGIN); sb.append("Control Thread"); sb.append(WebAdminResponderThread.COMPONENT_END); // ************************************** // Show Detail. sb.append(WebAdminResponderThread.BEGIN_TABLE); sb.append(WebAdminResponderThread.BEGIN_ROW); sb.append(WebAdminResponderThread.BEGIN_COL); sb.append(WebAdminResponderThread.BEGIN_TABLE); sb.append(WebAdminResponderThread.build2ColumnRow("UpTime", this.gsw.getElapsedTimeString())); sb.append(WebAdminResponderThread.build2ColumnRow("Group Name", this.my_group_name)); sb.append(WebAdminResponderThread.build2ColumnRow("This Address", this.my_addr.toString())); sb.append(WebAdminResponderThread.build2ColumnRow("Primary Coordinator Address", this.PRIMARY_COORDINATOR_ADDR.toString())); if (this.PRIMARY_COORDINATOR) { sb.append(WebAdminResponderThread.build2ColumnRow("Primary Coordinator", WebAdminResponderThread.POSITIVE_VALUE + Boolean.toString(this.PRIMARY_COORDINATOR)) + WebAdminResponderThread.POSITIVE_VALUE_END); } else { sb.append(WebAdminResponderThread.build2ColumnRow("Primary Coordinator", WebAdminResponderThread.NEUTRAL_VALUE + Boolean.toString(this.PRIMARY_COORDINATOR)) + WebAdminResponderThread.NEUTRAL_VALUE_END); } // End of Else Check for Primary. sb.append(WebAdminResponderThread.END_TABLE); sb.append(WebAdminResponderThread.END_COL); sb.append(WebAdminResponderThread.BEGIN_COL); sb.append(WebAdminResponderThread.BEGIN_TABLE); sb.append(WebAdminResponderThread.build2ColumnRow("Component Failure Count", Long.toString(this.FAILURE_COUNT))); sb.append(WebAdminResponderThread.build2ColumnRow("Control Stack Commands", Long.toString(this.stackcommands))); sb.append(WebAdminResponderThread.build2ColumnRow("Routed Received Messages", Long.toString(this.receivedstackcommands))); sb.append(WebAdminResponderThread.build2ColumnRow("Invalid Received Messages", Long.toString(this.receivedinvalidobjects))); sb.append(WebAdminResponderThread.build2ColumnRow("Membership Updates Received", Long.toString(this.membershipupdatesreceived))); //sb.append(WebAdminResponderThread.build2ColumnRow("Messages Waiting on Channel", // Long.toString(this.my_channel.getNumMessages()))); sb.append(WebAdminResponderThread.build2ColumnRow("Lap Time Messages From Input Stack", this.LP_ENTRY_FROM_COS.toString())); sb.append(WebAdminResponderThread.build2ColumnRow("Lap Time Reading Log Directory", this.LP_ENTRY_FROM_LOGDIR.toString())); sb.append(WebAdminResponderThread.END_TABLE); sb.append(WebAdminResponderThread.END_COL); sb.append(WebAdminResponderThread.END_ROW); sb.append(WebAdminResponderThread.END_TABLE); // **************************** // Now Provide Channel Detail. //sb.append("<PRE>"); //sb.append( this.my_channel.printProtocolSpec(true) ); //sb.append("</PRE>"); // *************************** // Return Formatted Status. return sb.toString(); } // End of Protected GetStatus Method. /** * Provides Logging of Stack Traces from Exceptions detail on the Nested Stack Trace * from Severe Runtime Errors. */ private void logStackTrace(final Exception e, final String METHODNAME, final String MSGNUM) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); pw.close(); FrameworkLogger.log(CLASSNAME, METHODNAME, FrameworkLoggerLevel.SEVERE, MSGNUM, new String[]{e.getMessage(), sw.toString()}); } // End of logStackTrace private Method. } ///:~ End of Class IRRChangeLogRestoreServiceControlThread