001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.geronimo.monitoring.snapshot;
017:
018: import java.sql.Connection;
019: import java.sql.DriverManager;
020: import java.sql.ResultSet;
021: import java.sql.Statement;
022: import java.text.SimpleDateFormat;
023: import java.util.ArrayList;
024: import java.util.Calendar;
025: import java.util.Date;
026: import java.util.HashMap;
027: import java.util.Iterator;
028: import java.util.TreeMap;
029:
030: import javax.sql.DataSource;
031:
032: import org.apache.commons.logging.Log;
033: import org.apache.commons.logging.LogFactory;
034:
035: public class SnapshotDBHelper {
036: private static Log log = LogFactory.getLog(SnapshotDBHelper.class);
037: // field attributes for the Statistics table in the DB
038: private static final String SNAPSHOT_TIME = "snapshot_time";
039: private static final String MBEANNAME = "mbeanName";
040: private static final String STATSVALUELIST = "statsValueList";
041: private static final String STATSNAMELIST = "statsNameList";
042: // Connection object used for DB interaction
043: private static Connection conn = null;
044: // Data Sources
045: private static DataSource activeDS = null;
046: private static DataSource archiveDS = null;
047:
048: public SnapshotDBHelper() {
049:
050: }
051:
052: public SnapshotDBHelper(DataSource activeDS, DataSource archiveDS) {
053: SnapshotDBHelper.activeDS = activeDS;
054: SnapshotDBHelper.archiveDS = archiveDS;
055: }
056:
057: /**
058: * @return A map: mbeanName --> ArrayList of statistic attributes for that mbean
059: */
060: public HashMap<String, ArrayList<String>> getAllSnapshotStatAttributes() {
061: openActiveConnection();
062: HashMap<String, ArrayList<String>> retval = new HashMap<String, ArrayList<String>>();
063: try {
064: Statement stmt = conn.createStatement();
065: String query = "SELECT DISTINCT mbeanName, statsNameList FROM MBeans";
066: ResultSet rs = stmt.executeQuery(query);
067: // add each mbean/statsValue combination to retval
068: while (rs.next()) {
069: String mbeanName = rs.getString(MBEANNAME);
070: String statsNameStr = rs.getString(STATSNAMELIST);
071: String[] statsNameList = statsNameStr.split(",");
072: ArrayList<String> mbeanAttributeList = new ArrayList<String>();
073: // copy from String[] to ArrayList<String>
074: for (int i = 0; i < statsNameList.length; i++) {
075: mbeanAttributeList.add(statsNameList[i]);
076: }
077: retval.put(mbeanName, mbeanAttributeList);
078: }
079: } catch (Exception e) {
080: log.error(e.getMessage(), e);
081: } finally {
082: closeConnection();
083: }
084: return retval;
085: }
086:
087: /**
088: *
089: * @return The number of snapshots present in the active database
090: */
091: public Long getSnapshotCount() {
092: long retval = 0;
093: try {
094: openActiveConnection();
095: Statement stmt = conn.createStatement();
096: String query = "SELECT COUNT(DISTINCT snapshot_time) FROM Statistics";
097: ResultSet rs = stmt.executeQuery(query);
098: rs.next();
099: retval = rs.getLong(1);
100: } catch (Exception e) {
101: log.error(e.getMessage(), e);
102: } finally {
103: closeConnection();
104: }
105: return new Long(retval);
106: }
107:
108: /**
109: * @param numberOfSnapshots - the number of latest snapshots to look at
110: * @return A hashmap which maps an mbean --> a hashmap with an attribute name and its value . All values will be the max.
111: */
112: public HashMap<String, HashMap<String, Long>> fetchMaxSnapshotData(
113: Integer numberOfSnapshots) {
114: return fetchMaxOrMinSnapshotData(numberOfSnapshots, true);
115: }
116:
117: /**
118: * @param numberOfSnapshots - the number of latest snapshots to look at
119: * @return A hashmap which maps an mbean --> a hashmap with an attribute name and its value . All values will be the min.
120: */
121: public HashMap<String, HashMap<String, Long>> fetchMinSnapshotData(
122: Integer numberOfSnapshots) {
123: return fetchMaxOrMinSnapshotData(numberOfSnapshots, false);
124: }
125:
126: /**
127: * @param numberOfSnapshots - the number of latest snapshots to look at.
128: * @param isMax - true if the result should be all maximum values. otherwise, false.
129: * @return A hashmap which maps an mbean --> a hashmap with an attribute name and its value . All values will be the min
130: * or max, depending on the isMax parameter.
131: */
132: private HashMap<String, HashMap<String, Long>> fetchMaxOrMinSnapshotData(
133: Integer numberOfSnapshots, boolean isMax) {
134: openActiveConnection();
135: ResultSet snapshotTimeTable = fetchSnapshotTimesFromDB();
136: HashMap<String, HashMap<String, Long>> stats = new HashMap<String, HashMap<String, Long>>();
137: try {
138: // for each snapshot in the table
139: while (snapshotTimeTable.next()) {
140: Long snapshotTime = snapshotTimeTable
141: .getLong(SNAPSHOT_TIME);
142: // retrieve the snapshot information by time
143: ResultSet snapshotData = fetchSnapshotDataFromDB(snapshotTime);
144: // for each statistic, perform a relaxation
145: while (snapshotData.next()) {
146: String mbean = snapshotData.getString(MBEANNAME);
147: // get map associated with mbean
148: HashMap<String, Long> mbeanMap = stats.get(mbean);
149: if (mbeanMap == null) {
150: mbeanMap = new HashMap<String, Long>();
151: }
152: String[] statsNameList = snapshotData.getString(
153: STATSNAMELIST).split(",");
154: String[] statsValueList = snapshotData.getString(
155: STATSVALUELIST).split(",");
156: assert (statsNameList.length == statsValueList.length);
157: // for each statname/statsvalue combo in an mbean
158: for (int i = 0; i < statsNameList.length; i++) {
159: String statsName = statsNameList[i];
160: Long maxStatsValue = mbeanMap.get(statsName);
161: // give maxStatsValue some value if there isn't one
162: if (maxStatsValue == null) {
163: if (isMax) {
164: maxStatsValue = new Long(0);
165: } else {
166: maxStatsValue = Long.MAX_VALUE;
167: }
168: }
169: // relax
170: if (isMax) {
171: maxStatsValue = new Long(Math.max(Long
172: .parseLong(statsValueList[i]),
173: maxStatsValue.longValue()));
174: } else {
175: maxStatsValue = new Long(Math.min(Long
176: .parseLong(statsValueList[i]),
177: maxStatsValue.longValue()));
178: }
179: // save name/value back into mbeanMap
180: mbeanMap.put(statsName, maxStatsValue);
181: }
182: // save mbeanMap back into stats
183: stats.put(mbean, mbeanMap);
184: }
185:
186: // compute the remaining snapshots left to look at
187: numberOfSnapshots--;
188: // discontinue once we have looked at numberOfSnapshots snapshots
189: if (numberOfSnapshots == 0) {
190: break;
191: }
192: }
193: } catch (Exception e) {
194: log.error(e.getMessage(), e);
195: } finally {
196: closeConnection();
197: }
198: return stats;
199: }
200:
201: /**
202: * @param ds
203: * @param aggregateStats
204: * @return Returns a boolean if the snapshot statistics were successfully added
205: * to the DB.
206: */
207: public boolean addSnapshotToDB(
208: HashMap<String, HashMap<String, Long>> aggregateStats) {
209: boolean success = true;
210: // get the current time from 1970
211: String currTime = "";
212: currTime += (new Date()).getTime();
213: try {
214: // for each mbean
215: for (Iterator itt = aggregateStats.keySet().iterator(); itt
216: .hasNext();) {
217: String mbean = (String) itt.next();
218: // prepare the statsNameList and statsValueList beforehand
219: String statsNameList = "", statsValueList = "";
220: for (Iterator<String> it = aggregateStats.get(mbean)
221: .keySet().iterator(); it.hasNext();) {
222: String statsName = it.next();
223: Long statsValue = aggregateStats.get(mbean).get(
224: statsName);
225: if (statsNameList.length() == 0
226: || statsValueList.length() == 0) {
227: // do not add a comma because this is the first occurrence
228: statsValueList += statsValue.toString();
229: statsNameList += statsName;
230: } else {
231: // add a comma
232: statsValueList += "," + statsValue.toString();
233: statsNameList += "," + statsName;
234: }
235: }
236:
237: // start talking to DB
238: openActiveConnection();
239: Statement stmt = conn.createStatement();
240: HashMap stats = aggregateStats.get(mbean);
241: //--------Ensure MBeans are in place
242: int mbeanId = getMBeanId(mbean);
243: if (mbeanId != -1) {
244: // mbean already exists in the db
245: } else {
246: // doesn't exist in the db so add it
247: // add mbean record to the db
248: stmt
249: .executeUpdate("INSERT INTO MBeans (mbeanName, statsNameList) VALUES ("
250: + surroundWithQuotes(mbean)
251: + ","
252: + surroundWithQuotes(statsNameList)
253: + ")");
254: mbeanId = getMBeanId(mbean);
255: }
256:
257: // insert the statistics into Statistics table
258: stmt.executeUpdate(prepareInsertSnapshotStatement(
259: currTime, statsValueList, mbeanId));
260: closeConnection();
261: }
262: } catch (Exception e) {
263: log.error(e.getMessage(), e);
264: success = false;
265: } finally {
266: closeConnection();
267: }
268:
269: // go through the archiving process
270: try {
271: int retentionDays = Integer
272: .parseInt(SnapshotConfigXMLBuilder
273: .getAttributeValue("retention"));
274: long retentionMillis = (long) (retentionDays) * 86400000; // convert from days to milliseconds
275: archiveSnapshots(Long.parseLong(currTime) - retentionMillis);
276: } catch (Exception e) {
277: log
278: .warn("Cannot archive snapshots because attribute 'retention' is not present in snapshot-config.xml.");
279: }
280: return success;
281: }
282:
283: /**
284: * Moves records from the ActiveDB to the ArchiveDB. The records that are moved
285: * are those whose snapshot_times exceed the retention period
286: * @param cutOffTime - in milliseconds
287: */
288: private void archiveSnapshots(long cutOffTime) {
289: // for each successful update of Snapshots/Statistics table
290: // increment or decrement these counters to ensure that nothing is being
291: // lost in between. If these counters are non-zero, some records have been
292: // lost.
293: int snapshotsOver = 0;
294: int statisticsOver = 0;
295: try {
296: openActiveConnection();
297: ResultSet overDueSnapshotTimes = getOverDueSnapshotTimes(cutOffTime);
298: ArrayList<Long> overdueTimes = new ArrayList<Long>();
299: // save overdue times into an array list for later usage
300: while (overDueSnapshotTimes.next()) {
301: overdueTimes.add(overDueSnapshotTimes
302: .getLong(SNAPSHOT_TIME));
303: }
304: closeConnection();
305: // for each overdue snapshot time
306: // -transfer all records associated with that snaphot_time to ArchiveDB
307: for (int i = 0; i < overdueTimes.size(); i++) {
308: long snapshotTime = overdueTimes.get(i);
309: openActiveConnection();
310: ResultSet rsSnapshotData = fetchSnapshotDataFromDB(new Long(
311: snapshotTime));
312: HashMap<String, HashMap<String, Long>> snapshotData = new HashMap<String, HashMap<String, Long>>();
313: while (rsSnapshotData.next()) {
314: // extract values from sql table
315: String mbeanName = rsSnapshotData
316: .getString(MBEANNAME);
317: String statsNameList = rsSnapshotData
318: .getString(STATSNAMELIST);
319: String statsValueList = rsSnapshotData
320: .getString(STATSVALUELIST);
321: Long snapshot_time = rsSnapshotData
322: .getLong(SNAPSHOT_TIME);
323: // get a connection to the archive db too
324: Connection archiveConn = archiveDS.getConnection();
325: Statement archiveStmt = archiveConn
326: .createStatement();
327: //--------Ensure MBeans are in place
328: int mbeanId = getMBeanIdFromArchive(mbeanName);
329: if (mbeanId != -1) {
330: // mbean already exists in the db
331: } else {
332: // doesn't exist in the db so add it
333: // add mbean record to the db
334: archiveStmt
335: .executeUpdate("INSERT INTO MBeans (mbeanName, statsNameList) VALUES ("
336: + surroundWithQuotes(mbeanName)
337: + ", "
338: + surroundWithQuotes(statsNameList)
339: + ")");
340: mbeanId = getMBeanIdFromArchive(mbeanName);
341: }
342: // ensure Statistics table has record of mbeanId, snapshotId, statsValue, statsName
343: String updateStr = prepareInsertSnapshotStatement(
344: snapshot_time + "", statsValueList, mbeanId);
345: statisticsOver += archiveStmt
346: .executeUpdate(updateStr);
347: // close connection to archiveDB
348: archiveConn.close();
349: }
350: closeConnection();
351: }
352: // for each snapshot time, remove all instances that is associated with in
353: // in the active DB
354: for (int i = 0; i < overdueTimes.size(); i++) {
355: long snapshotTime = overdueTimes.get(i);
356: openActiveConnection();
357: Statement stmt = conn.createStatement();
358: // remove from Statistics table
359: String statisticsUpdate = "DELETE FROM Statistics WHERE snapshot_time="
360: + snapshotTime;
361: statisticsOver -= stmt.executeUpdate(statisticsUpdate);
362: closeConnection();
363: }
364: } catch (Exception e) {
365: log.error(e.getMessage(), e);
366: } finally {
367: closeConnection();
368: }
369:
370: // ensure that the transferring was good
371: if (snapshotsOver != 0) {
372: log
373: .warn("Transferred snapshots was completed, but some things were lost.");
374: }
375: if (statisticsOver != 0) {
376: log
377: .warn("Transferred statistics was completed, but some things were lost.");
378: }
379: }
380:
381: /**
382: * @param cutOffTime
383: * @return An SQL table contain a column of all the times that did not make the cutOffTime.
384: */
385: private ResultSet getOverDueSnapshotTimes(long cutOffTime) {
386: try {
387: Statement stmt = conn.createStatement();
388: String query = "SELECT DISTINCT snapshot_time FROM Statistics WHERE snapshot_time < "
389: + cutOffTime;
390: return stmt.executeQuery(query);
391: } catch (Exception e) {
392: log.error(e.getMessage(), e);
393: }
394: return null;
395: }
396:
397: /**
398: * @param mbean
399: * @return The mbean id of the mbean from table ArchiveDB.MBean. Returns -1 if record does not exist.
400: */
401: private int getMBeanIdFromArchive(String mbean) throws Exception {
402: int retval = -1;
403: Connection archiveConn = archiveDS.getConnection();
404: Statement stmt = archiveConn.createStatement();
405: ResultSet rs = stmt
406: .executeQuery("SELECT id FROM MBeans WHERE mbeanName="
407: + surroundWithQuotes(mbean));
408: if (rs.next()) {
409: retval = rs.getInt("id");
410: }
411: stmt.close();
412: archiveConn.close();
413: return retval;
414: }
415:
416: /**
417: * @param mbean
418: * @return The mbean id of the mbean from table ActiveDB.MBean. Returns -1 if record does not exist.
419: */
420: private int getMBeanId(String mbean) throws Exception {
421: int retval = -1;
422: Connection conn = activeDS.getConnection();
423: Statement stmt = conn.createStatement();
424: ResultSet rs = stmt
425: .executeQuery("SELECT id FROM MBeans WHERE mbeanName="
426: + surroundWithQuotes(mbean));
427: if (rs.next()) {
428: retval = rs.getInt("id");
429: }
430: stmt.close();
431: conn.close();
432: return retval;
433: }
434:
435: /**
436: * @param snapshot_time
437: * @param statsValueList
438: * @param mbeanId
439: * @return Returns an SQL insert statement for one statistic given the correct information.
440: */
441: public String prepareInsertSnapshotStatement(String snapshot_time,
442: String statsValueList, int mbeanId) {
443: String retval = "INSERT INTO Statistics (snapshot_time, statsValueList, mbeanId) VALUES (";
444: retval += snapshot_time;
445: retval += ",";
446: retval += surroundWithQuotes(statsValueList);
447: retval += ",";
448: retval += mbeanId;
449: retval += ")";
450: return retval;
451: }
452:
453: /**
454: * @param s
455: * @return A String with ' at the beginning and end
456: */
457: private String surroundWithQuotes(String s) {
458: return "'" + s.trim() + "'";
459: }
460:
461: /**
462: * Fetches the data stored from the snapshot thread and returns
463: * it in a ArrayList with each element being a HashMap of the attribute
464: * mapping to the statistic. Grabs 'numberOfSnapshots' snapshots. Grabs
465: * one snapshot per 'everyNthsnapshot'
466: *
467: * @param numberOfSnapshot
468: * @param everyNthSnapshot
469: * @return ArrayList
470: */
471: public ArrayList<HashMap<String, HashMap<String, Object>>> fetchData(
472: Integer numberOfSnapshot, Integer everyNthSnapshot) {
473: ArrayList<HashMap<String, HashMap<String, Object>>> stats = new ArrayList<HashMap<String, HashMap<String, Object>>>();
474: openActiveConnection();
475: // get all records in the database grouped and ordered by time
476: ResultSet table = fetchSnapshotTimesFromDB();
477: // iterate through the table and finds the times (which uniquely IDs a snapshot)
478: // that are wanted and queries the rest of the DB using the time as the condition
479: // (i.e. the ones that are in the c*n-th snapshot where c <= numberOfSnapshot
480: // and n == everyNthSnapshot)
481: int nthSnapshot = 0;
482: try {
483: while (table.next()) {
484: Long snapshotTime = table.getLong(SNAPSHOT_TIME);
485: // grab 0*nth, 1*nth, 2*nth snapshot up to min(numberOfSnapshot*everyNthSnapshot, size of the table)
486: if (nthSnapshot % everyNthSnapshot == 0) {
487: HashMap<String, HashMap<String, Object>> snapshotData = packageSnapshotData(snapshotTime);
488: stats.add(0, snapshotData);
489: numberOfSnapshot--;
490: }
491: nthSnapshot++;
492: // no more snapshots needs to be looked at, we have successfully acquired our goal
493: if (numberOfSnapshot == 0) {
494: break;
495: }
496: }
497: } catch (Exception e) {
498: log.error(e.getMessage(), e);
499: } finally {
500: closeConnection();
501: }
502: return stats;
503: }
504:
505: /**
506: * @param snapshotTime
507: * @return A hashmap in the form <String1, HashMap> where String1 is the mbean name
508: * and HashMap is a map containing a <String2, Object> where String2 is an attribute name
509: * and Object is the value. Additionally, if String is "times" then it maps to a HashMap
510: * containing snapshot_time and snapshot_date information.
511: */
512: private HashMap<String, HashMap<String, Object>> packageSnapshotData(
513: Long snapshotTime) {
514: HashMap<String, HashMap<String, Object>> snapshotPkg = new HashMap<String, HashMap<String, Object>>();
515: openActiveConnection();
516: ResultSet snapshotData = fetchSnapshotDataFromDB(snapshotTime);
517: try {
518: // for each record save it somewhere in the snapshotPkg
519: while (snapshotData.next()) {
520: String currMBean = snapshotData.getString(MBEANNAME);
521: // get the information for the mbean defined by currMBean
522: HashMap<String, Object> mbeanInfo = snapshotPkg
523: .get(currMBean);
524: if (mbeanInfo == null) {
525: mbeanInfo = new HashMap<String, Object>();
526: }
527: // get statistics from resultset
528: String statsValueStr = snapshotData
529: .getString(STATSVALUELIST);
530: String statsNameStr = snapshotData
531: .getString(STATSNAMELIST);
532: String[] statsValueList = statsValueStr.split(",");
533: String[] statsNameList = statsNameStr.split(",");
534: assert (statsValueList.length == statsNameList.length);
535: // for each statsValue/statsName, save it
536: for (int i = 0; i < statsValueList.length; i++) {
537: long statValue = Long.parseLong(statsValueList[i]);
538: mbeanInfo
539: .put(statsNameList[i], new Long(statValue));
540: }
541: // save the hashmap into the snapshotpkg
542: snapshotPkg.put(currMBean, mbeanInfo);
543: }
544: } catch (Exception e) {
545: log.error(e.getMessage(), e);
546: } finally {
547: closeConnection();
548: }
549: // add the time and date
550: HashMap<String, Object> timeMap = new HashMap<String, Object>();
551: timeMap.put(SNAPSHOT_TIME, snapshotTime);
552: snapshotPkg.put("times", timeMap);
553:
554: return snapshotPkg;
555: }
556:
557: /**
558: * @param snapshotTime
559: * @return Returns a ResultSet with all statistic information that matches the snapshot_time.
560: */
561: private ResultSet fetchSnapshotDataFromDB(Long snapshotTime) {
562: String query = "SELECT S.statsValueList AS statsValueList, M.statsNameList AS statsNameList, S.snapshot_time AS snapshot_time, M.mbeanName AS mbeanName FROM Statistics S, MBeans M WHERE S.snapshot_time="
563: + snapshotTime;
564: query += " AND S.mbeanId=M.id";
565: ResultSet retval = null;
566: try {
567: if (conn.isClosed()) {
568: openActiveConnection();
569: }
570: Statement stmt = conn.createStatement();
571: retval = stmt.executeQuery(query);
572: } catch (Exception e) {
573: log.error(e.getMessage(), e);
574: }
575: return retval;
576: }
577:
578: /**
579: * @return Returns a ResultSet with one column (snapshot_time) sorted in descending order
580: */
581: private ResultSet fetchSnapshotTimesFromDB() {
582: String query = "SELECT DISTINCT snapshot_time FROM Statistics ORDER BY snapshot_time DESC";
583: ResultSet retval = null;
584: try {
585: if (conn.isClosed()) {
586: openActiveConnection();
587: }
588: Statement stmt = conn.createStatement();
589: retval = stmt.executeQuery(query);
590: } catch (Exception e) {
591: log.error(e.getMessage(), e);
592: }
593: return retval;
594: }
595:
596: /**
597: * Opens the global connection to activeDB
598: */
599: private void openActiveConnection() {
600: try {
601: conn = activeDS.getConnection();
602: } catch (Exception e) {
603: log.error(e.getMessage(), e);
604: }
605: }
606:
607: /**
608: * Opens the global connection to archiveDB
609: */
610: private void openArchiveConnection() {
611: try {
612: conn = archiveDS.getConnection();
613: } catch (Exception e) {
614: log.error(e.getMessage(), e);
615: }
616: }
617:
618: /**
619: * Closes the global connection to a DB
620: */
621: private void closeConnection() {
622: if (conn != null) {
623: try {
624: conn.close();
625: } catch (Exception e) {
626: log.error(e.getMessage(), e);
627: }
628: }
629: }
630:
631: /**
632: * @param mbeanName
633: * @param statsName
634: * @param numberOfSnapshots
635: * @param everyNthSnapshot
636: * @return HashMap which maps from a snapshot_time --> value of the mbean.statsName at that time
637: */
638: public TreeMap<Long, Long> getSpecificStatistics(String mbeanName,
639: String statsName, int numberOfSnapshots,
640: int everyNthSnapshot, boolean showArchived) {
641: openActiveConnection();
642: TreeMap<Long, Long> stats = new TreeMap<Long, Long>();
643: int nthSnapshot = 0;
644: // attempt to get as many snapshots from the active db as possible
645: try {
646: Statement stmt = conn.createStatement();
647: int mbeanId = getMBeanId(mbeanName);
648: if (mbeanId == -1) {
649: log.error(mbeanName
650: + " does not exist in the database.");
651: } else {
652: String query = "SELECT DISTINCT snapshot_time, statsValueList, statsNameList FROM Statistics, MBeans M WHERE mbeanId="
653: + mbeanId
654: + " AND mbeanId=M.id ORDER BY snapshot_time DESC";
655: ResultSet rs = stmt.executeQuery(query);
656: // iterate through the table paying attention to those at everyNthSnapshot-th position
657: while (rs.next()) {
658: // every nth snapshot I save the information into my returning hashmap
659: if (nthSnapshot % everyNthSnapshot == 0) {
660: String[] statsValueList = rs.getString(
661: STATSVALUELIST).split(",");
662: String[] statsNameList = rs.getString(
663: STATSNAMELIST).split(",");
664: assert (statsValueList.length == statsNameList.length);
665: Long statsValue = null;
666: for (int i = 0; i < statsNameList.length; i++) {
667: if (statsNameList[i].equals(statsName)) {
668: long value = Long
669: .parseLong(statsValueList[i]);
670: statsValue = new Long(value);
671: }
672: }
673: // exit function after error
674: if (statsValue == null) {
675: log.warn("Statistics name '" + statsName
676: + "' does not exist");
677: return stats;
678: } else {
679: stats.put(rs.getLong(SNAPSHOT_TIME),
680: statsValue);
681: numberOfSnapshots--;
682: }
683: }
684: // update counter
685: nthSnapshot++;
686: // enough data, end this thing
687: if (numberOfSnapshots == 0) {
688: break;
689: }
690: }
691: }
692: } catch (Exception e) {
693: log.error(e.getMessage(), e);
694: } finally {
695: closeConnection();
696: }
697:
698: nthSnapshot = 0;
699:
700: // attempt to get the remaining snapshots requested from the archive DB
701: // iff the showArchive flag is set
702: if (showArchived && numberOfSnapshots != 0) {
703: try {
704: openArchiveConnection(); // connection to the Archive DB
705: Statement stmt = conn.createStatement();
706: int mbeanId = getMBeanId(mbeanName);
707: if (mbeanId == -1) {
708: log.error(mbeanName
709: + " does not exist in the database.");
710: } else {
711: String query = "SELECT DISTINCT snapshot_time, statsValueList, statsNameList FROM Statistics, MBeans M WHERE mbeanId="
712: + mbeanId
713: + " AND mbeanId=M.id ORDER BY snapshot_time DESC";
714: ResultSet rs = stmt.executeQuery(query);
715: // iterate through the table paying attention to those at everyNthSnapshot-th position
716: while (rs.next()) {
717: // every nth snapshot I save the information into my returning hashmap
718: if (nthSnapshot % everyNthSnapshot == 0) {
719: String[] statsValueList = rs.getString(
720: STATSVALUELIST).split(",");
721: String[] statsNameList = rs.getString(
722: STATSNAMELIST).split(",");
723: assert (statsValueList.length == statsNameList.length);
724: Long statsValue = null;
725: for (int i = 0; i < statsNameList.length; i++) {
726: if (statsNameList[i].equals(statsName)) {
727: long value = Long
728: .parseLong(statsValueList[i]);
729: statsValue = new Long(value);
730: }
731: }
732: // exit function after error
733: if (statsValue == null) {
734: log.warn("Statistics name '"
735: + statsName
736: + "' does not exist");
737: return stats;
738: } else {
739: stats.put(rs.getLong(SNAPSHOT_TIME),
740: statsValue);
741: numberOfSnapshots--;
742: }
743: }
744: // update counter
745: nthSnapshot++;
746: // enough data, end this thing
747: if (numberOfSnapshots == 0) {
748: break;
749: }
750: }
751: }
752: } catch (Exception e) {
753: log.error(e.getMessage(), e);
754: } finally {
755: closeConnection();
756: }
757: }
758: return stats;
759: }
760:
761: /**
762: * Sets the necessary data sources for this helper to talk to the db
763: * @param activeDS
764: * @param archiveDS
765: */
766: public void setDataSources(DataSource active, DataSource archive) {
767: activeDS = active;
768: archiveDS = archive;
769: }
770: }
|