/** Start collecting global monitoring information for the replication domain. */ private void initializePendingMonitorData() { // Let's process our directly connected DS // - in the ServerHandler for a given DS1, the stored state contains : // -- the max CSN produced by DS1 // -- the last CSN consumed by DS1 from DS2..n // - in the ReplicationDomainDB/ReplicaDB, the built-in state contains: // -- the max CSN produced by each server // So for a given DS connected we can take the state and the max from // the DS/state. for (ServerHandler ds : domain.getConnectedDSs().values()) { final int serverId = ds.getServerId(); final ServerState dsState = ds.getServerState().duplicate(); CSN maxCSN = dsState.getCSN(serverId); if (maxCSN == null) { // This directly connected LS has never produced any change maxCSN = new CSN(0, 0, serverId); } pendingMonitorData.setMaxCSN(maxCSN); pendingMonitorData.setLDAPServerState(serverId, dsState); pendingMonitorData.setFirstMissingDate(serverId, ds.getApproxFirstMissingDate()); } // Then initialize the max CSN for the LS that produced something // - from our own local db state // - whatever they are directly or indirectly connected final ServerState dbServerState = domain.getLatestServerState(); pendingMonitorData.setRSState(domain.getLocalRSServerId(), dbServerState); for (CSN storedCSN : dbServerState) { pendingMonitorData.setMaxCSN(storedCSN); } }
/** * Recomputes the monitor data for this replication server domain. * * @return The recomputed monitor data for this replication server domain. * @throws InterruptedException If this thread is interrupted while waiting for a response. */ public ReplicationDomainMonitorData recomputeMonitorData() throws InterruptedException { // Only allow monitor recalculation at a time. synchronized (pendingMonitorLock) { if (monitorDataLastBuildDate + monitorDataLifeTime < TimeThread.getTime()) { try { DN baseDN = domain.getBaseDN(); // Prevent out of band monitor responses from updating our pending // table until we are ready. synchronized (pendingMonitorDataLock) { // Clear the pending monitor data. pendingMonitorDataServerIDs.clear(); pendingMonitorData = new ReplicationDomainMonitorData(); initializePendingMonitorData(); // Send the monitor requests to the connected replication servers. for (ServerHandler rs : domain.getConnectedRSs().values()) { final int serverId = rs.getServerId(); MonitorRequestMsg msg = new MonitorRequestMsg(domain.getLocalRSServerId(), serverId); try { rs.send(msg); // Only register this server ID to pending table if we were able // to send the message. pendingMonitorDataServerIDs.add(serverId); } catch (IOException e) { // Log a message and do a best effort from here. logger.error( ERR_SENDING_REMOTE_MONITOR_DATA_REQUEST, baseDN, serverId, e.getMessage()); } } // Create the pending response latch based on the number of expected // monitor responses. pendingMonitorDataLatch = new CountDownLatch(pendingMonitorDataServerIDs.size()); } // Wait for the responses to come back. pendingMonitorDataLatch.await(5, TimeUnit.SECONDS); // Log messages for replication servers that have gone or come back. synchronized (pendingMonitorDataLock) { // Log servers that have come back. for (int serverId : monitorDataLateServers) { // Ensure that we only log once per server: don't fill the // error log with repeated messages. if (!pendingMonitorDataServerIDs.contains(serverId)) { logger.info(NOTE_MONITOR_DATA_RECEIVED, baseDN, serverId); } } // Log servers that have gone away. for (int serverId : pendingMonitorDataServerIDs) { // Ensure that we only log once per server: don't fill the // error log with repeated messages. if (!monitorDataLateServers.contains(serverId)) { logger.warn(WARN_MISSING_REMOTE_MONITOR_DATA, baseDN, serverId); } } // Remember which servers were late this time. monitorDataLateServers.clear(); monitorDataLateServers.addAll(pendingMonitorDataServerIDs); } // Store the new computed data as the reference synchronized (pendingMonitorDataLock) { // Now we have the expected answers or an error occurred pendingMonitorData.completeComputing(); monitorData = pendingMonitorData; monitorDataLastBuildDate = TimeThread.getTime(); } } finally { synchronized (pendingMonitorDataLock) { // Clear pending state. pendingMonitorData = null; pendingMonitorDataLatch = null; pendingMonitorDataServerIDs.clear(); } } } } return monitorData; }