modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java
| 10 +
modules/enterprise/agent/src/etc/java-service-wrapper/rhq-agent-wrapper.conf
| 4
modules/enterprise/agent/src/etc/rhq-agent-wrapper.bat
| 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/AvailabilityManagerBean.java
| 51 +++++++---
4 files changed, 53 insertions(+), 16 deletions(-)
New commits:
commit 719e2c127f24f7467ecc3a371d9797f6598880c0
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Dec 5 09:34:19 2013 -0500
[1038256] Windows 2008 - Invalid agent service after upgrade (on remote agent
machine)
This problem resulted from the work in Bug 1016609, when we introduced
the use of RHQ_JAVA_EXE_FILE_PATH and deprecated the use of
RHQ_AGENT_JAVA_EXE_FILE_PATH (among several simplifications of our
env properties). The issue with that change was the fact that existing
windows agent services (remote agents, not handled by rhqctl) included
set.RHQ_AGENT_JAVA_EXE_FILE_PATH in the service "path to executable", for
use by the service wrapper. But the new rhq-agent-wrapper.conf expected
RHQ_JAVA_EXE_FILE_PATH to be set when formulating its command string.
This was only an issue for existing agents that would be auto-upgraded. Agent
auto-upgrade does not update the existing service, it only restarts it after
the agent update. So, the "path to executable" remains unchanged and
therefore
passes only the legacy property. Note that auto-upgrade does the right thing,
it should *not* replace the service in order to update its definition. Doing
this could lose the RUN_AS password, which may have been set interactively
when the agent was initially installed.
The solution should be good, the rhq-agent-wrapper.conf has been reverted to
use RHQ_AGENT_JAVA_EXE_FILE_PATH. We still completely support the
new RHQ env properties, like RHQ_JAVA_EXE_FILE_PATH, but will supply
the legacy property at service install time. That gives up backward
compatibility while keeping the use of RHQ_AGENT_JAVA_EXE_FILE_PATH
internal.
diff --git a/modules/enterprise/agent/src/etc/java-service-wrapper/rhq-agent-wrapper.conf
b/modules/enterprise/agent/src/etc/java-service-wrapper/rhq-agent-wrapper.conf
index 3f3712e..a510ea9 100644
--- a/modules/enterprise/agent/src/etc/java-service-wrapper/rhq-agent-wrapper.conf
+++ b/modules/enterprise/agent/src/etc/java-service-wrapper/rhq-agent-wrapper.conf
@@ -33,7 +33,7 @@
# set.RHQ_AGENT_PASSWORD - the password of the user that is to
# run the service. Only used if
# RHQ_AGENT_PASSWORD_PROMPT is FALSE.
-# set.RHQ_JAVA_EXE_FILE_PATH - Java executable
+# set.RHQ_AGENT_JAVA_EXE_FILE_PATH - Java executable
#*****************************************************************************
# Load in the specific environment for the RHQ agent instance to start
@@ -43,7 +43,7 @@
# Start Properties
#*****************************************************************************
# Java JVM Executable (quotes not needed)
-wrapper.java.command=%RHQ_JAVA_EXE_FILE_PATH%
+wrapper.java.command=%RHQ_AGENT_JAVA_EXE_FILE_PATH%
# Java Main class. This class must implement the WrapperListener interface. (quotes not
needed)
wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
diff --git a/modules/enterprise/agent/src/etc/rhq-agent-wrapper.bat
b/modules/enterprise/agent/src/etc/rhq-agent-wrapper.bat
index 90e9666..657f701 100644
--- a/modules/enterprise/agent/src/etc/rhq-agent-wrapper.bat
+++ b/modules/enterprise/agent/src/etc/rhq-agent-wrapper.bat
@@ -146,7 +146,9 @@ if /i "%1"=="install" (
if not defined RHQ_AGENT_PASSWORD_PROMPT set RHQ_AGENT_PASSWORD_PROMPT=true
)
- "%RHQ_AGENT_WRAPPER_EXE_FILE_PATH%" -i
"%RHQ_AGENT_WRAPPER_CONF_FILE_PATH%"
"set.RHQ_AGENT_HOME=%RHQ_AGENT_HOME%"
"set.RHQ_AGENT_INSTANCE_NAME=%RHQ_AGENT_INSTANCE_NAME%"
"set.RHQ_JAVA_EXE_FILE_PATH=%RHQ_JAVA_EXE_FILE_PATH%"
"set.RHQ_AGENT_OS_PLATFORM=%RHQ_AGENT_OS_PLATFORM%"
"set.RHQ_AGENT_WRAPPER_LOG_DIR_PATH=%RHQ_AGENT_WRAPPER_LOG_DIR_PATH%"
!_WRAPPER_NTSERVICE_ACCOUNT! %_DEBUG_OPTS%
+ rem note that we set RHQ_AGENT_JAVA_EXE_FILE_PATH on purpose. The services use this
legacy env var, as opposed to
+ rem RHQ_JAVA_EXE_FILE_PATH, to be backward compatible with existing services that get
auto-upgraded.
+ "%RHQ_AGENT_WRAPPER_EXE_FILE_PATH%" -i
"%RHQ_AGENT_WRAPPER_CONF_FILE_PATH%"
"set.RHQ_AGENT_HOME=%RHQ_AGENT_HOME%"
"set.RHQ_AGENT_INSTANCE_NAME=%RHQ_AGENT_INSTANCE_NAME%"
"set.RHQ_AGENT_JAVA_EXE_FILE_PATH=%RHQ_JAVA_EXE_FILE_PATH%"
"set.RHQ_AGENT_OS_PLATFORM=%RHQ_AGENT_OS_PLATFORM%"
"set.RHQ_AGENT_WRAPPER_LOG_DIR_PATH=%RHQ_AGENT_WRAPPER_LOG_DIR_PATH%"
!_WRAPPER_NTSERVICE_ACCOUNT! %_DEBUG_OPTS%
if ERRORLEVEL 1 goto error
goto done
)
commit 544dc80ce4c22e399d3ca607108896feb6ebd5b6
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Wed Dec 4 13:36:49 2013 -0500
[1037616] Pull calls to find current availability out of the processing loop
Optimization work based on BZ-supplied patch. For a batch of Availabilities
being processed, pull latest availabilities for the resources in one DB
round trip as opposed to once for each resource. Still beiong careful to
repair issues when no, or multiple, latest entries are found.
diff --git
a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java
b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java
index 2297af9..a44a2ff 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java
@@ -64,6 +64,11 @@ import org.rhq.core.domain.resource.Resource;
+ " WHERE av.resource.id = :resourceId " //
+ " AND av.endTime IS NULL " //
+ "ORDER BY av.startTime ASC "), // this order by is on purpose - for
handling NonUniqueResultException problems
+ @NamedQuery(name = Availability.FIND_LATEST_BY_RESOURCE_IDS, query = "" //
+ + " SELECT av " //
+ + " FROM Availability av " //
+ + " WHERE av.resource.id IN :resourceIds " //
+ + " AND av.endTime IS NULL "), //
@NamedQuery(name = Availability.FIND_BY_RESOURCE, query = "" //
+ " SELECT av " //
+ " FROM Availability av " //
@@ -88,7 +93,7 @@ import org.rhq.core.domain.resource.Resource;
+ "SELECT new
org.rhq.core.domain.resource.composite.ResourceIdWithAvailabilityComposite(av.resource.id,
av) " //
+ " FROM Availability av " //
+ " WHERE av.resource.agent.id = :agentId " //
- + " AND av.resource.parentResource IS NOT NULL " //
+ + " AND av.resource.parentResource IS NOT NULL " //
+ " AND ((av.availabilityType <> :availabilityType AND
av.availabilityType <> :disabled AND :availabilityType IS NOT NULL) " //
+ " OR (av.availabilityType IS NOT NULL AND :availabilityType IS
NULL) " //
+ " OR (av.availabilityType IS NULL AND :availabilityType IS NOT
NULL)) " //
@@ -139,6 +144,7 @@ public class Availability implements Serializable {
private static final long serialVersionUID = 1L;
public static final String FIND_CURRENT_BY_RESOURCE =
"Availability.findCurrentByResource";
+ public static final String FIND_LATEST_BY_RESOURCE_IDS =
"Availability.findLatestByResourceIds";
public static final String FIND_BY_RESOURCE =
"Availability.findByResource";
public static final String FIND_BY_RESOURCE_NO_SORT =
"Availability.findByResourceNoSort";
public static final String FIND_PLATFORM_COMPOSITE_BY_AGENT_AND_NONMATCHING_TYPE =
"Availability.findPlatformCompositeByAgentAndNonmatchingType";
@@ -199,7 +205,7 @@ public class Availability implements Serializable {
*
* @param resource
* @param startTime if null set to current time
- * @param type if null this will be set to UNKNOWN
+ * @param type if null this will be set to UNKNOWN
*/
public Availability(Resource resource, Long startTime, AvailabilityType type) {
if (resource == null) {
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/AvailabilityManagerBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/AvailabilityManagerBean.java
index 76fe117..e54b167 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/AvailabilityManagerBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/AvailabilityManagerBean.java
@@ -25,6 +25,7 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import javax.ejb.EJB;
import javax.ejb.Stateless;
@@ -93,13 +94,15 @@ public class AvailabilityManagerBean implements
AvailabilityManagerLocal, Availa
static {
+ // The value of 200 has been settled upon after testing several batch sizes. If
changed it still must be less
+ // than 1000 for Oracle IN clause limitation reasons.
int mergeBatchSize = 200;
try {
mergeBatchSize =
Integer.parseInt(System.getProperty("rhq.server.availability.merge.batch.size",
"200"));
} catch (Throwable t) {
//
}
- MERGE_BATCH_SIZE = mergeBatchSize;
+ MERGE_BATCH_SIZE = (mergeBatchSize > 999) ? 999 : mergeBatchSize;
}
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
@@ -811,8 +814,28 @@ public class AvailabilityManagerBean implements
AvailabilityManagerLocal, Availa
// We will alert only on the avails for enabled resources. Keep track of any that
are disabled.
List<Availability> disabledAvailabilities = new
ArrayList<Availability>();
- Query q = entityManager.createNamedQuery(Availability.FIND_CURRENT_BY_RESOURCE);
- int count = 0;
+
+ Query q =
entityManager.createNamedQuery(Availability.FIND_LATEST_BY_RESOURCE_IDS);
+ List<Integer> resourceIds = new
ArrayList<Integer>(availabilities.size());
+ for (Availability reported : availabilities) {
+ resourceIds.add(reported.getResource().getId());
+ }
+ q.setParameter("resourceIds", resourceIds);
+ List<Availability> latestAvailabilitiesList = q.getResultList();
+ resourceIds.clear(); // perhaps helps GC
+
+ // populate Map of resourceIds to latestAvailability
+ // there should be a single latest avail per resource. mark any situation where
we have multiple
+ Object nonUniqueMarker = new Object();
+ Map<Integer, Object> latestAvailabilities = new
HashMap(availabilities.size() + 100);
+ for (Availability latestAvailability : latestAvailabilitiesList) {
+ Integer resourceId = latestAvailability.getResource().getId();
+ if (latestAvailabilities.containsKey(resourceId)) {
+ latestAvailabilities.put(resourceId, nonUniqueMarker);
+ } else {
+ latestAvailabilities.put(resourceId, latestAvailability);
+ }
+ }
for (Availability reported : availabilities) {
@@ -820,13 +843,12 @@ public class AvailabilityManagerBean implements
AvailabilityManagerLocal, Availa
reported.setEndTime(null);
// get the latest avail for the reported resource
- q.setParameter("resourceId", reported.getResource().getId());
+ //q.setParameter("resourceId", reported.getResource().getId());
+ Integer resourceId = reported.getResource().getId();
+ Object latestObject = latestAvailabilities.get(resourceId);
Availability latest = null;
- try {
- latest = (Availability) q.getSingleResult();
-
- } catch (NoResultException nre) {
+ if (null == latestObject) { // this is like NoResultException
// This should not happen unless the Resource in the report is stale,
which can happen in certain
// sync scenarios. A Resource is given its initial
Availability/ResourceAvailability when it is
// persisted so it is guaranteed to have Availability, so, the Resource
must not exist. At least
@@ -873,7 +895,7 @@ public class AvailabilityManagerBean implements
AvailabilityManagerLocal, Availa
continue;
}
}
- } catch (NonUniqueResultException nure) {
+ } else if (latestObject == nonUniqueMarker) { // this is like
NonUniqueResultException
// This condition should never happen. In my world of la-la land,
I've done everything
// correctly so this never happens. But, due to the asynchronous nature
of things,
// I have to believe that this still might happen (albeit rarely). If it
does happen,
@@ -881,10 +903,13 @@ public class AvailabilityManagerBean implements
AvailabilityManagerLocal, Availa
// has 2 or more availabilities with endTime of null, we need to delete
all but the
// latest one (the one whose start time is the latest). This should
correct the
// problem and allow us to continue processing availability reports for
that resource
- log.warn("Resource [" + reported.getResource() + "] has
multiple availabilities without an endtime ["
- + nure.getMessage() + "] - will attempt to remove the extra
ones\n" + mergeInfo.toString(false));
+ log.warn("Resource [" + reported.getResource()
+ + "] has multiple availabilities without an endtime - will
attempt to remove the extra ones\n"
+ + mergeInfo.toString(false));
try {
+ q =
entityManager.createNamedQuery(Availability.FIND_CURRENT_BY_RESOURCE);
+ q.setParameter("resourceId", resourceId);
List<Availability> latestList = q.getResultList();
@@ -906,6 +931,8 @@ public class AvailabilityManagerBean implements
AvailabilityManagerLocal, Availa
+ "]", t);
continue;
}
+ } else {
+ latest = (Availability) latestObject;
}
AvailabilityType latestType = latest.getAvailabilityType();
@@ -953,6 +980,8 @@ public class AvailabilityManagerBean implements
AvailabilityManagerLocal, Availa
}
}
+ latestAvailabilities.clear(); // perhaps helps GC
+
// notify alert condition cache manager for all reported avails for for enabled
resources
availabilities.removeAll(disabledAvailabilities);
notifyAlertConditionCacheManager("mergeAvailabilityReport",