modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/event/EventManagerBean.java | 13 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/performance/test/AvailabilityInsertPurgeTest.java | 11 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/performance/test/EventsInsertPurgeTest.java | 170 ++++++++++ modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/reporting/ExcelExporter.java | 43 +- modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseSetupInterceptor.java | 39 ++ modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseState.java | 4 6 files changed, 245 insertions(+), 35 deletions(-)
New commits: commit 28acd40f69627f32523cd6e0f7c46f6f7b4ec1d4 Author: Heiko W. Rupp hwr@redhat.com Date: Thu Oct 14 12:38:51 2010 +0200
Move required database state to class level.
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/performance/test/AvailabilityInsertPurgeTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/performance/test/AvailabilityInsertPurgeTest.java index 6bc40b5..17520c3 100644 --- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/performance/test/AvailabilityInsertPurgeTest.java +++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/performance/test/AvailabilityInsertPurgeTest.java @@ -47,7 +47,6 @@ import org.rhq.helpers.perftest.support.testng.DatabaseSetupInterceptor; import org.rhq.helpers.perftest.support.testng.DatabaseState; import org.rhq.helpers.perftest.support.testng.PerformanceReporting;
-import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Listeners; import org.testng.annotations.Test; @@ -61,6 +60,7 @@ import org.testng.annotations.Test; @Test(groups = "PERF") @Listeners({ DatabaseSetupInterceptor.class }) @PerformanceReporting(exporter=ExcelExporter.class) +@DatabaseState(url = "perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip", dbVersion="2.94") public class AvailabilityInsertPurgeTest extends AbstractEJB3PerformanceTest {
ResourceManagerLocal resourceManager; @@ -72,8 +72,7 @@ public class AvailabilityInsertPurgeTest extends AbstractEJB3PerformanceTest { private static final String ROUND__FORMAT = "Round %6d"; private static final String PURGE__FORMAT = "Purge %6d"; private static final int[] ROUNDS = new int[]{1000,2000,3000,5000,10000}; - // private static final int[] ROUNDS = new int[]{10,20}; - private Subject overlord ; +// private static final int[] ROUNDS = new int[]{10,20};
@BeforeMethod public void beforeMethod() { @@ -106,7 +105,6 @@ public class AvailabilityInsertPurgeTest extends AbstractEJB3PerformanceTest { * @throws Exception If anything goes wrong * @see #ROUNDS for the number of availability reports per round */ - @DatabaseState(url = "perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip", dbVersion="2.94") public void testAlternating() throws Exception { Subject overlord = LookupUtil.getSubjectManager().getOverlord();
@@ -184,7 +182,6 @@ public class AvailabilityInsertPurgeTest extends AbstractEJB3PerformanceTest { * @throws Exception If anything goes wrong * @see #ROUNDS for the number of availability reports per round */ - @DatabaseState(url = "perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip", dbVersion="2.94") public void testRandom() throws Exception { Subject overlord = LookupUtil.getSubjectManager().getOverlord();
@@ -254,7 +251,6 @@ public class AvailabilityInsertPurgeTest extends AbstractEJB3PerformanceTest { * @throws Exception If anything goes wrong * @see #ROUNDS for the number of availability reports per round */ - @DatabaseState(url = "perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip", dbVersion="2.94") public void testAlwaysUp() throws Exception { Subject overlord = LookupUtil.getSubjectManager().getOverlord();
@@ -327,7 +323,6 @@ public class AvailabilityInsertPurgeTest extends AbstractEJB3PerformanceTest { * @throws Exception If anything goes wrong * @see #ROUNDS for the number of availability reports per round */ - @DatabaseState(url = "perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip", dbVersion="2.94") public void testAlternatingWithAlert() throws Exception { Subject overlord = LookupUtil.getSubjectManager().getOverlord();
@@ -411,6 +406,4 @@ public class AvailabilityInsertPurgeTest extends AbstractEJB3PerformanceTest { assertLinear(purge1000,purge5000,5,"Purge3");
} - - }
commit ab845b5e3713b03f77e79735cef81a6fb2dff1d1 Author: Heiko W. Rupp hwr@redhat.com Date: Thu Oct 14 11:54:38 2010 +0200
Change naming of sheets to Class.method
diff --git a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/reporting/ExcelExporter.java b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/reporting/ExcelExporter.java index 6662b71..1314ce8 100644 --- a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/reporting/ExcelExporter.java +++ b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/reporting/ExcelExporter.java @@ -116,16 +116,22 @@ public class ExcelExporter implements PerformanceReportExporter { */ private void createDetailsSheet(Workbook wb, Map<String,Long> timings, ITestResult result) {
- Sheet sheet = wb.getSheet(result.getName()); + String name = result.getTestClass().getName(); + if (name.contains(".")) + name = name.substring(name.lastIndexOf(".")+1); + name += "." + result.getName(); + + Sheet sheet = wb.getSheet(name); if (sheet ==null) - sheet = wb.createSheet(result.getName()); + sheet = wb.createSheet(name);
Row row = appendRow(sheet); Cell cell = row.createCell(0); cell.setCellStyle(boldText); cell.setCellValue("Class"); - String name = result.getTestClass().getName(); - name = name.replace("org.rhq.enterprise.server.performance.test.",""); + name = result.getTestClass().getName(); + if (name.contains(".")) + name = name.substring(name.lastIndexOf(".")+1); row.createCell(1).setCellValue(name); row = appendRow(sheet);
@@ -197,32 +203,29 @@ public class ExcelExporter implements PerformanceReportExporter { * @param result the TestNG result object */ private void createOverviewEntry(Sheet sheet, long testTime, ITestResult result) { - // Class name + // Test name Row row = appendRow(sheet); Cell cell = row.createCell(0); cell.setCellType(Cell.CELL_TYPE_STRING); String name = result.getTestClass().getName(); - name = name.replace("org.rhq.enterprise.server.performance.test.",""); + if (name.contains(".")) + name = name.substring(name.lastIndexOf(".")+1); + name += "." + result.getName(); cell.setCellValue(name);
- // Test name - cell = row.createCell(1); - cell.setCellType(Cell.CELL_TYPE_STRING); - cell.setCellValue(result.getName()); - // success ? - cell = row.createCell(2); + cell = row.createCell(1); cell.setCellType(Cell.CELL_TYPE_BOOLEAN); cell.setCellValue(result.isSuccess());
// timing from TestNG - cell = row.createCell(3); + cell = row.createCell(2); cell.setCellType(Cell.CELL_TYPE_NUMERIC); cell.setCellStyle(integerStyle); cell.setCellValue(result.getEndMillis()-result.getStartMillis());
// timing of our business logic - cell = row.createCell(4); + cell = row.createCell(3); cell.setCellType(Cell.CELL_TYPE_NUMERIC); cell.setCellStyle(integerStyle); cell.setCellValue(testTime); @@ -239,25 +242,21 @@ public class ExcelExporter implements PerformanceReportExporter {
Cell cell = row.createCell(0); cell.setCellStyle(boldText); - cell.setCellValue("Class"); - cell = row.createCell(1); - cell.setCellStyle(boldText); cell.setCellValue("Name"); - cell = row.createCell(2); + cell = row.createCell(1); cell.setCellStyle(boldText); cell.setCellValue("Success"); - cell = row.createCell(3); + cell = row.createCell(2); cell.setCellStyle(boldText); cell.setCellValue("TestNG timing"); cell.setCellStyle(boldText); - cell = row.createCell(4); + cell = row.createCell(3); cell.setCellValue("Perf timing"); cell.setCellStyle(boldText);
sheet.autoSizeColumn(0); - sheet.autoSizeColumn(1); + sheet.autoSizeColumn(2); sheet.autoSizeColumn(3); - sheet.autoSizeColumn(4);
}
commit 85d31a919a4912995d39ba6f5097d9fc8988a910 Author: Heiko W. Rupp hwr@redhat.com Date: Thu Oct 14 10:15:55 2010 +0200
First event insertion and purge test.
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/performance/test/EventsInsertPurgeTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/performance/test/EventsInsertPurgeTest.java new file mode 100644 index 0000000..0332905 --- /dev/null +++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/performance/test/EventsInsertPurgeTest.java @@ -0,0 +1,170 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.server.performance.test; + +import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.event.Event; +import org.rhq.core.domain.event.EventDefinition; +import org.rhq.core.domain.event.EventSeverity; +import org.rhq.core.domain.event.EventSource; +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceCategory; +import org.rhq.core.domain.resource.ResourceType; +import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal; +import org.rhq.enterprise.server.core.AgentManagerLocal; +import org.rhq.enterprise.server.event.EventManagerLocal; +import org.rhq.enterprise.server.measurement.AvailabilityManagerLocal; +import org.rhq.enterprise.server.resource.ResourceManagerLocal; +import org.rhq.enterprise.server.system.SystemManagerLocal; +import org.rhq.enterprise.server.test.AbstractEJB3PerformanceTest; +import org.rhq.enterprise.server.util.LookupUtil; +import org.rhq.helpers.perftest.support.reporting.ExcelExporter; +import org.rhq.helpers.perftest.support.testng.DatabaseSetupInterceptor; +import org.rhq.helpers.perftest.support.testng.DatabaseState; +import org.rhq.helpers.perftest.support.testng.PerformanceReporting; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +import javax.persistence.EntityManager; +import javax.persistence.Query; +import java.sql.SQLException; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Performance test the events subsystem + * + * @author Heiko W. Rupp + */ +@Test(groups = "PERF") +@Listeners({ DatabaseSetupInterceptor.class }) +@PerformanceReporting(exporter=ExcelExporter.class) +@DatabaseState(url = "perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip", dbVersion="2.94") +public class EventsInsertPurgeTest extends AbstractEJB3PerformanceTest { + + private static final int ROUNDS = 20000; + private static final int NUM_SOURCES = 10; + private static final int LINES_PER_REPORT = 50; + ResourceManagerLocal resourceManager; + AvailabilityManagerLocal availabilityManager; + AgentManagerLocal agentManager; + SystemManagerLocal systemManager; + AlertDefinitionManagerLocal alertDefinitionManager; + EventManagerLocal eventManager; + private static final int MILLIS_APART = 2000; + private static final String ROUND__FORMAT = "Round %6d"; + private static final String PURGE__FORMAT = "Purge %6d"; + + + @BeforeMethod + public void beforeMethod() { + Date now = new Date(); + System.out.println(">>>>> beforeMethod (AI Purge Test) === " + now.getTime()); + try { + this.availabilityManager = LookupUtil.getAvailabilityManager(); + this.resourceManager = LookupUtil.getResourceManager(); + this.agentManager = LookupUtil.getAgentManager(); + this.systemManager = LookupUtil.getSystemManager(); + this.alertDefinitionManager = LookupUtil.getAlertDefinitionManager(); + this.eventManager = LookupUtil.getEventManager(); + /* + * NOTE: do not try to get Subjects or other DB stuff in here, as they will only + * be available after this method has finished and the DatabaseSetupInterceptor + * has initialized the database. + */ + } catch (Throwable t) { + // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them + // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)! + t.printStackTrace(); + throw new RuntimeException(t); + } + } + + /** + * This test insertsevents from NUM_SOURCES sources into the + * event subsystem, where each set of events is LINES_PER_REPORT long. + * In total ROUNDS are inserted. + * After this, events are purged in two steps: first the first half of them + * and then the remaining ones. + * @throws Exception + */ + public void testSimpleInserts() throws Exception { + Subject overlord = LookupUtil.getSubjectManager().getOverlord(); + + + EntityManager em = getEntityManager(); + Query q = em.createQuery("SELECT r FROM Resource r"); + List<Resource> resources = q.getResultList(); + Resource res = resources.get(0); + if (!(res.getResourceType().getCategory()== ResourceCategory.PLATFORM)) + res = resourceManager.getPlaformOfResource(overlord,res.getId()); + ResourceType type = res.getResourceType(); + + EventDefinition def ; + Set<EventDefinition> eventDefs = type.getEventDefinitions(); + if (eventDefs!=null && !eventDefs.isEmpty()) { + def = eventDefs.iterator().next(); + } + else { + throw new RuntimeException("No event definition found, should not happen"); + } + + + EventSource[] evSrc = new EventSource[NUM_SOURCES]; + for (int i = 0; i < NUM_SOURCES; i++) { + evSrc[i] = new EventSource("ESource"+1, def, res); + } + long now = new Date().getTime() - ROUNDS * LINES_PER_REPORT; + + for (int round = 1; round < ROUNDS; round++) { + + Map<EventSource, Set<Event>> events = new HashMap<EventSource, Set<Event>>(); + for (int sourceNum = 0 ; sourceNum < NUM_SOURCES; sourceNum++) { + Set<Event> eventSet = new HashSet<Event>(); + for (int i = 0 ; i < LINES_PER_REPORT; i++) { + Event ev = new Event("EType", "ESource"+sourceNum, now+round*i, EventSeverity.INFO, "This is a 2nd test", evSrc[sourceNum]); + eventSet.add(ev); + } + events.put(evSrc[sourceNum], eventSet); + } + startTiming("add"); + eventManager.addEventData(events); + endTiming("add"); + } + + try { + startTiming("purge_half"); + eventManager.purgeEventData(new Date(now+(ROUNDS/2)*LINES_PER_REPORT)); + endTiming("purge_half"); + startTiming("purge_final"); + eventManager.purgeEventData(new Date()); + endTiming("purge_final"); + } catch (SQLException e) { + e.printStackTrace(); + throw e; + } + + } + +}
commit 6a51d174ea673b88d052cca23c53fc186c1bf478 Author: Heiko W. Rupp hwr@redhat.com Date: Thu Oct 14 10:02:09 2010 +0200
Be somewhat more verbose on exceptions
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/event/EventManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/event/EventManagerBean.java index 31b283b..293c456 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/event/EventManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/event/EventManagerBean.java @@ -18,6 +18,7 @@ */ package org.rhq.enterprise.server.event;
+import java.sql.BatchUpdateException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; @@ -193,6 +194,14 @@ public class EventManagerBean implements EventManagerLocal, EventManagerRemote { } catch (Throwable t) { // TODO what do we want to do here ? log.warn("addEventData: Insert of events failed : " + t.getMessage()); + if (t instanceof SQLException) { + SQLException e = (SQLException) t; + Exception e2 = e.getNextException(); + if (e2!=null) + log.warn(" : " + e2.getMessage()); + if (t.getCause()!=null) + log.warn(" : " + t.getCause().getMessage()); + } } finally { JDBCUtil.safeClose(conn); } @@ -345,9 +354,9 @@ public class EventManagerBean implements EventManagerLocal, EventManagerRemote { criteria.addFilterStartTime(begin); criteria.addFilterEndTime(end);
- /* + /* * if the bucket computation is pushed into the database, it saves on data transfer across the wire. this - * solution is currently querying N number of strings (event.severity) and N number of longs (event.timestamp), + * solution is currently querying N number of strings (event.severity) and N number of longs (event.timestamp), * where N is the number of events between 'begin' and 'end'. if the severity buckets are computed in a single * query, the wire load would only be K integers, where K is the bucketCount. */
commit baeefa7b2f1e2afe98bebebaf9525c840b8bd6d3 Author: Heiko W. Rupp hwr@redhat.com Date: Wed Oct 13 10:19:23 2010 +0200
Allow to put the DatabaseState annotation at class level too.
diff --git a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseSetupInterceptor.java b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseSetupInterceptor.java index 57cd217..d7f10ef 100644 --- a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseSetupInterceptor.java +++ b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseSetupInterceptor.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.SQLException; @@ -43,6 +44,12 @@ import org.rhq.helpers.perftest.support.input.InputStreamProvider; import org.testng.IInvokedMethod; import org.testng.IInvokedMethodListener; import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterSuite; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.BeforeTest;
import javax.naming.InitialContext;
@@ -138,10 +145,40 @@ public class DatabaseSetupInterceptor implements IInvokedMethodListener {
}
+ /** + * Obtain the required database state by looking for the @DatabaseState annotation. + * Lookup is first done at method level and if not found done at class level. + * @param method Method that TestNG is about to invoke + * @return the desired database state or null if @DatabaseState is not given. + * @see org.rhq.helpers.perftest.support.testng.DatabaseState + */ private static DatabaseState getRequiredDatabaseState(IInvokedMethod method) { Method javaMethod = method.getTestMethod().getMethod();
- return javaMethod.getAnnotation(DatabaseState.class); + DatabaseState annotation = javaMethod.getAnnotation(DatabaseState.class); + if (annotation==null) { + System.out.println("Method : " + javaMethod.getName()); + + boolean skip = false; + + // Filter out methods that are marked as setup/tear down + Annotation[] annots = javaMethod.getAnnotations(); + for (Annotation an : annots) { + System.out.println(" : " + an.toString()); + if (an.annotationType().equals(BeforeMethod.class) || an.annotationType().equals(AfterMethod.class) || + an.annotationType().equals(BeforeSuite.class) || an.annotationType().equals(AfterSuite.class) || + an.annotationType().equals(BeforeTest.class) || an.annotationType().equals(AfterTest.class) + ) + skip = true; + } + + if (!skip) + annotation = javaMethod.getDeclaringClass().getAnnotation(DatabaseState.class); + else + System.out.println(" ..... Skipped"); + + } + return annotation; }
diff --git a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseState.java b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseState.java index b7e66fa..9a7c476 100644 --- a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseState.java +++ b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseState.java @@ -28,11 +28,13 @@ import org.rhq.helpers.perftest.support.FileFormat;
/** * An annotation to associate a test method with a required state of the database. + * The annotation can be given at class or method level, where a method level annotation + * overrides a class level one. * * @author Lukas Krejci */ @Retention(value = RetentionPolicy.RUNTIME) -@Target(value = { ElementType.METHOD }) +@Target(value = { ElementType.METHOD, ElementType.TYPE }) public @interface DatabaseState {
/**
rhq-commits@lists.fedorahosted.org