List of usage examples for javax.persistence NonUniqueResultException getMessage
public String getMessage()
From source file:org.rhq.enterprise.server.measurement.AvailabilityManagerBean.java
@SuppressWarnings("unchecked") public boolean mergeAvailabilityReport(AvailabilityReport report) { int reportSize = report.getResourceAvailability().size(); String agentName = report.getAgentName(); StopWatch watch = new StopWatch(); if (reportSize == 0) { log.error("Agent [" + agentName + "] sent an empty availability report. This is a bug, please report it"); return true; // even though this report is bogus, do not ask for an immediate full report to avoid unusual infinite recursion due to this error condition }// w ww . jav a 2 s . com if (log.isDebugEnabled()) { if (reportSize > 1) { log.debug("Agent [" + agentName + "]: processing availability report of size: " + reportSize); } } // translate data into Availability objects for downstream processing List<Availability> availabilities = new ArrayList<Availability>(report.getResourceAvailability().size()); for (AvailabilityReport.Datum datum : report.getResourceAvailability()) { availabilities.add(new Availability(new Resource(datum.getResourceId()), datum.getStartTime(), datum.getAvailabilityType())); } // We will alert only on the avails for enabled resources. Keep track of any that are disabled. List<Availability> disabledAvailabilities = new ArrayList<Availability>(); boolean askForFullReport = false; Integer agentToUpdate = agentManager.getAgentIdByName(agentName); // if this report is from an agent update the lastAvailreport time if (!report.isEnablementReport() && agentToUpdate != null) { // do this now, before we might clear() the entity manager availabilityManager.updateLastAvailabilityReport(agentToUpdate.intValue()); } int numInserted = 0; // if this report is from an agent, and is a changes-only report, and the agent appears backfilled, // then we need to skip this report so as not to waste our time> Then, immediately request and process // a full report because, obviously, the agent is no longer down but the server thinks // it still is down - we need to know the availabilities for all the resources on that agent if (!report.isEnablementReport() && report.isChangesOnlyReport() && agentManager.isAgentBackfilled(agentToUpdate.intValue())) { askForFullReport = true; } else { Query q = entityManager.createNamedQuery(Availability.FIND_CURRENT_BY_RESOURCE); q.setFlushMode(FlushModeType.COMMIT); int count = 0; for (Availability reported : availabilities) { if ((++count % 100) == 0) { entityManager.flush(); entityManager.clear(); } // availability reports only tell us the current state at the start time; end time is ignored/must be null reported.setEndTime(null); try { q.setParameter("resourceId", reported.getResource().getId()); Availability latest = (Availability) q.getSingleResult(); AvailabilityType latestType = latest.getAvailabilityType(); AvailabilityType reportedType = reported.getAvailabilityType(); // If the current avail is DISABLED, and this report is not trying to re-enable the resource, // Then ignore the reported avail. if (AvailabilityType.DISABLED == latestType) { if (!(report.isEnablementReport() && (AvailabilityType.UNKNOWN == reportedType))) { disabledAvailabilities.add(reported); continue; } } if (reported.getStartTime() >= latest.getStartTime()) { //log.info( "new avail (latest/reported)-->" + latest + "/" + reported ); // the new availability data is for a time after our last known state change // we are runlength encoded, so only persist data if the availability changed if (latest.getAvailabilityType() != reported.getAvailabilityType()) { entityManager.persist(reported); numInserted++; latest.setEndTime(reported.getStartTime()); latest = entityManager.merge(latest); updateResourceAvailability(reported); } // our last known state was unknown, ask for a full report to ensure we are in sync with agent if (latest.getAvailabilityType() == AvailabilityType.UNKNOWN) { askForFullReport = true; } } else { //log.info( "past avail (latest/reported)==>" + latest + "/" + reported ); // The new data is for a time in the past, probably an agent sending a report after // a network outage has been corrected but after we have already backfilled. // We need to insert it into our past timeline. insertAvailability(reported); numInserted++; // this is an unusual report - ask the agent for a full report so as to ensure we are in sync with agent askForFullReport = true; } } catch (NoResultException nre) { // This condition should never happen. An initial, unknown, Availability/ResourceAvailability // are created at resource persist time. But, just in case, handle it... log.warn("Resource [" + reported.getResource() + "] has no availability without an endtime [" + nre.getMessage() + "] - will attempt to create one\n" + report.toString(false)); entityManager.persist(reported); updateResourceAvailability(reported); numInserted++; } catch (NonUniqueResultException nure) { // 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, // and we do nothing about it - bad things arise. So, if we find that a resource // 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" + report.toString(false)); q.setParameter("resourceId", reported.getResource().getId()); List<Availability> latest = q.getResultList(); // delete all but the last one (our query sorts in ASC start time order) int latestCount = latest.size(); for (int i = 0; i < (latestCount - 1); i++) { entityManager.remove(latest.get(i)); } updateResourceAvailability(latest.get(latestCount - 1)); // this is an unusual report - ask the agent for a full report so as to ensure we are in sync with agent askForFullReport = true; } } MeasurementMonitor.getMBean().incrementAvailabilityReports(report.isChangesOnlyReport()); MeasurementMonitor.getMBean().incrementAvailabilitiesInserted(numInserted); MeasurementMonitor.getMBean().incrementAvailabilityInsertTime(watch.getElapsed()); watch.reset(); } // notify alert condition cache manager for all reported avails for for enabled resources availabilities.removeAll(disabledAvailabilities); notifyAlertConditionCacheManager("mergeAvailabilityReport", availabilities.toArray(new Availability[availabilities.size()])); if (!report.isEnablementReport()) { // a single report comes from a single agent - update the agent's last availability report timestamp if (agentToUpdate != null) { // don't bother asking for a full report if the one we are currently processing is already full if (askForFullReport && report.isChangesOnlyReport()) { log.debug("The server is unsure that it has up-to-date availabilities for agent [" + agentName + "]; asking for a full report to be sent"); return false; } } else { log.error("Could not figure out which agent sent availability report. " + "This error is harmless and should stop appearing after a short while if the platform of the agent [" + agentName + "] was recently removed. In any other case this is a bug." + report); } } return true; // everything is OK and things look to be in sync }