From 1387e05a497147cd1a320c9651a47f122e942b93 Mon Sep 17 00:00:00 2001
From: kenneth_suter <kenneth_suter@localhost>
Date: Mon, 09 Apr 2007 12:24:58 +0000
Subject: [PATCH] historical log for upgrader tool
---
opends/src/quicksetup/org/opends/quicksetup/upgrader/HistoricalRecord.java | 291 ++++++++++++++++++++++++++++++++
opends/src/quicksetup/org/opends/quicksetup/util/Utils.java | 19 ++
opends/src/quicksetup/org/opends/quicksetup/Installation.java | 7
opends/src/quicksetup/org/opends/quicksetup/upgrader/HistoricalLog.java | 139 +++++++++++++++
opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java | 81 ++++++++
5 files changed, 526 insertions(+), 11 deletions(-)
diff --git a/opends/src/quicksetup/org/opends/quicksetup/Installation.java b/opends/src/quicksetup/org/opends/quicksetup/Installation.java
index 4b902f5..35f8a8b 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/Installation.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/Installation.java
@@ -490,7 +490,6 @@
return new File(getHistoryDirectory(), HISTORY_LOG_FILE_NAME);
}
-
/**
* Gets the directory config/upgrade.
* @return File representing the config/upgrade directory
@@ -570,9 +569,9 @@
}
/**
- * Returns the path to the status-panel file.
- *
- * @return the path to the status-panel file.
+ * Gets the status panel command file appropriate for the current operating
+ * system.
+ * @return File object representing the status panel command
*/
public File getStatusPanelCommandFile() {
File statusPanelCommandFile;
diff --git a/opends/src/quicksetup/org/opends/quicksetup/upgrader/HistoricalLog.java b/opends/src/quicksetup/org/opends/quicksetup/upgrader/HistoricalLog.java
new file mode 100644
index 0000000..5144c5b
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/upgrader/HistoricalLog.java
@@ -0,0 +1,139 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.upgrader;
+
+import org.opends.quicksetup.util.Utils;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.io.*;
+
+/**
+ * Log of past upgrade/reversion events that is backed by the file
+ * [install root]/history/log.
+ */
+public class HistoricalLog {
+
+ private File file;
+
+ /**
+ * Creates a historical log backed by <code>file</code>. If file
+ * does not exist an attempt will be made to create it.
+ * @param file File containing the historical record
+ * @throws IOException if something goes wrong attempting to create
+ * a new historical record file
+ */
+ public HistoricalLog(File file) throws IOException {
+ this.file = file;
+ if (!file.exists()) {
+ Utils.createFile(file);
+ }
+ }
+
+ /**
+ * Gets a list of the historical records in the file.
+ * @return List of HistoricalRecord
+ * @throws IOException if there was an error reading the records file
+ */
+ public List<HistoricalRecord> getRecords() throws IOException {
+ List<HistoricalRecord> records = new ArrayList<HistoricalRecord>();
+ BufferedReader br = new BufferedReader(new FileReader(file));
+ String s;
+ while (null != (s = br.readLine())) {
+ records.add(HistoricalRecord.fromString(s));
+ }
+ return Collections.unmodifiableList(records);
+ }
+
+ /**
+ * Creates a new historical log record and appends a new log record to the
+ * log. A new operation ID is generated and returned so that future calls
+ * can use the same ID.
+ * @param from current version
+ * @param to version to upgrade to
+ * @param status of the upgrade
+ * @param note optional string with additional information
+ * @return Long operation ID that can be used in writing future logs
+ * @throws IOException if there is a problem appending the log to the file
+ */
+ public Long append(Integer from, Integer to,
+ HistoricalRecord.Status status, String note)
+ throws IOException
+ {
+ HistoricalRecord record = new HistoricalRecord(from, to, status, note);
+ Long id = record.getOperationId();
+ append(record);
+ return id;
+ }
+
+ /**
+ * Creates a new historical log record and appends a new log record to the
+ * log.
+ * @param id Long ID obtained from a call to
+ {@link org.opends.quicksetup.upgrader.HistoricalLog#
+ append(Integer, Integer,
+ org.opends.quicksetup.upgrader.HistoricalRecord.Status)}
+ * @param from current version
+ * @param to version to upgrade to
+ * @param status of the upgrade
+ * @param note optional string with additional information
+ * @throws IOException if there is a problem appending the log to the file
+ */
+ public void append(Long id, Integer from, Integer to,
+ HistoricalRecord.Status status, String note)
+ throws IOException
+ {
+ HistoricalRecord record = new HistoricalRecord(id, from, to, status, note);
+ append(record);
+ }
+
+ /**
+ * Appends a historical record to the log.
+ * @param record to append to the log file
+ * @throws IOException if there is a problem appending the record to the file
+ */
+ private void append(HistoricalRecord record) throws IOException {
+ BufferedWriter bw = null;
+ try {
+ bw = new BufferedWriter(new FileWriter(file, true));
+ bw.write(record.toString());
+ bw.newLine();
+ bw.flush();
+ } finally {
+ if (bw != null) {
+ try {
+ bw.close();
+ } catch (IOException ioe2) {
+ // do nothing;
+ }
+ }
+ }
+ }
+
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/upgrader/HistoricalRecord.java b/opends/src/quicksetup/org/opends/quicksetup/upgrader/HistoricalRecord.java
new file mode 100644
index 0000000..f4cf4a3
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/upgrader/HistoricalRecord.java
@@ -0,0 +1,291 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.upgrader;
+
+import java.util.StringTokenizer;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.text.SimpleDateFormat;
+
+/**
+ * A record in the historical log stored in [install root]/history/log.
+ */
+public class HistoricalRecord {
+
+ static private final Logger LOG =
+ Logger.getLogger(HistoricalRecord.class.getName());
+
+ static private String OPERATION = "operation:";
+
+ static private String TIME = "time:";
+
+ static private String FROM = "from:";
+
+ static private String TO = "to:";
+
+ static private String STATUS = "status:";
+
+ static private String NOTE = "note:";
+
+ static private String SEPARATOR = " ";
+
+ static private String DATE_FORMAT = "yyyyMMddHHmmss";
+
+ /**
+ * State of an upgrade.
+ */
+ enum Status {
+
+ STARTED("started"),
+
+ SUCCESS("success"),
+
+ FAILURE("failure");
+
+ private String representation;
+
+ /**
+ * Creates a State from a String.
+ * @param s string representation of a state
+ * @return Status created from <code>s</code>
+ */
+ static public Status fromString(String s) {
+ Status retOc = null;
+ Set<Status> all = EnumSet.allOf(Status.class);
+ for (Status oc : all) {
+ if (oc.toString().equals(s)) {
+ retOc = oc;
+ }
+ }
+ return retOc;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return representation;
+ }
+
+ private Status(String representation) {
+ this.representation = representation;
+ }
+
+ }
+
+ /**
+ * Creates a historical log record from its string representation.
+ * @param s string representation
+ * @return HistoricalRecord created from the string
+ * @throws IllegalArgumentException if the string is misformatted
+ */
+ static public HistoricalRecord fromString(String s)
+ throws IllegalArgumentException {
+ Long operationid = null;
+ Integer fromInt = null;
+ Integer toInt = null;
+ Status outcome = null;
+ Date date = null;
+ String note = null;
+ Exception creationError = null;
+ try {
+ StringTokenizer st = new StringTokenizer(s, SEPARATOR);
+
+ String token = st.nextToken();
+ String operationIdString = token.substring(OPERATION.length());
+ operationid = Long.parseLong(operationIdString);
+
+ token = st.nextToken();
+ String timeString = token.substring(TIME.length());
+ date = new SimpleDateFormat(DATE_FORMAT).parse(timeString);
+
+ token = st.nextToken();
+ String fromString = token.substring(FROM.length());
+ fromInt = new Integer(fromString);
+
+ token = st.nextToken();
+ String toString = token.substring(TO.length());
+ toInt = new Integer(toString);
+
+ token = st.nextToken();
+ String outcomeString = token.substring(STATUS.length());
+ outcome = Status.fromString(outcomeString);
+
+ if (st.hasMoreTokens()) {
+ token = st.nextToken("");
+ if (token != null) {
+ note = token.substring(NOTE.length());
+ }
+ }
+ } catch (Exception e) {
+ // There was a problem creating the record. Log the error and
+ // create the record with what we have already accumulated.
+ LOG.log(Level.INFO, "error creating historical log record", e);
+ creationError = e;
+ }
+ return new HistoricalRecord(operationid, date, fromInt,
+ toInt, outcome, note, creationError);
+ }
+
+ private Long operationId;
+
+ private Integer from;
+
+ private Integer to;
+
+ private Status status;
+
+ private Date date;
+
+ private String note;
+
+ /** true indicates there were not errors creating this record. */
+ private Exception creationError;
+
+ /**
+ * Creates a new historical record using the current time and generating.
+ * a new operation id
+ * @param from current version
+ * @param to version to upgrade to
+ * @param status of the upgrade
+ * @param note containing details of status; can be null
+ */
+ public HistoricalRecord(Integer from,
+ Integer to, Status status, String note) {
+ this.from = from;
+ this.to = to;
+ this.status = status;
+ this.date = new Date();
+ this.operationId = date.getTime();
+ this.note = note;
+ }
+
+ /**
+ * Creates a new historical record using the current time.
+ * @param operationId obtained from a previously created HistoricalRecord
+ * @param from current version
+ * @param to version to upgrade to
+ * @param status of the upgrade
+ * @param note containing details of status; can be null
+ */
+ public HistoricalRecord(Long operationId, Integer from,
+ Integer to, Status status, String note) {
+ this.from = from;
+ this.to = to;
+ this.status = status;
+ this.date = new Date();
+ this.operationId = operationId;
+ this.note = note;
+ }
+
+ /**
+ * Creates a new historical record using the current time.
+ * @param operationId obtained from a previously created HistoricalRecord
+ * @param from current version
+ * @param to version to upgrade to
+ * @param status of the upgrade
+ * @param note containing details of status; can be null
+ * @param creationError Exception that occurred while this record was
+ * being created
+ */
+ private HistoricalRecord(Long operationId, Date date, Integer from,
+ Integer to, Status status, String note,
+ Exception creationError) {
+ this.operationId = operationId;
+ this.from = from;
+ this.to = to;
+ this.status = status;
+ this.date = date;
+ this.note = note;
+ this.creationError = creationError;
+ }
+
+ /**
+ * Gets the operation ID associated with this record.
+ * @return Long ID of this operation
+ */
+ public Long getOperationId() {
+ return operationId;
+ }
+
+ /**
+ * Gets the Date the record was created.
+ * @return Date of the record
+ */
+ public Date getDate() {
+ return this.date;
+ }
+
+ /**
+ * Gets the Integer representing the SVN rev ID of the current installation.
+ * @return Integer version ID
+ */
+ public Integer getFromVersion() {
+ return this.from;
+ }
+
+ /**
+ * Gets the Integer representing the SVN rev ID of the installation being
+ * upgraded to.
+ * @return Integer version ID
+ */
+ public Integer getToVersion() {
+ return this.to;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ StringBuilder sb = new StringBuilder()
+ .append(OPERATION)
+ .append(operationId)
+ .append(SEPARATOR)
+ .append(TIME)
+ .append(new SimpleDateFormat(DATE_FORMAT).format(date))
+ .append(SEPARATOR)
+ .append(FROM)
+ .append(from)
+ .append(SEPARATOR)
+ .append(TO)
+ .append(to)
+ .append(SEPARATOR)
+ .append(STATUS)
+ .append(status);
+ if (note != null) {
+ sb.append(SEPARATOR)
+ .append(NOTE)
+ .append(note);
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java b/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
index 0fe630e..a6ce096 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
@@ -41,10 +41,7 @@
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
-import java.io.IOException;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileFilter;
+import java.io.*;
import static org.opends.quicksetup.Installation.*;
@@ -154,7 +151,7 @@
DATABASES_PATH_RELATIVE, // db
LOGS_PATH_RELATIVE, // logs
LOCKS_PATH_RELATIVE, // locks
- HISTORY_PATH_RELATIVE // history; TODO: should we do this?
+ HISTORY_PATH_RELATIVE // history
};
private ProgressStep currentProgressStep = UpgradeProgressStep.NOT_STARTED;
@@ -171,6 +168,11 @@
/** Directory where backup is kept in case the upgrade needs reversion. */
private File backupDirectory = null;
+ /** ID that uniquely identifieds this invocation of the Upgrader in the
+ * historical logs.
+ */
+ private Long historicalOperationId;
+
/**
* {@inheritDoc}
*/
@@ -317,11 +319,17 @@
// Reset exception just in case this application is rerun
// for some reason
runException = null;
+ Integer fromVersion = null;
+ Integer toVersion = null;
try {
try {
setCurrentProgressStep(UpgradeProgressStep.INITIALIZING);
initialize();
+ fromVersion = getStagedInstallation().getSvnRev();
+ toVersion = getInstallation().getSvnRev();
+ this.historicalOperationId =
+ writeInitialHistoricalRecord(fromVersion, toVersion);
} catch (ApplicationException e) {
LOG.log(Level.INFO, "error initializing upgrader", e);
throw e;
@@ -390,8 +398,8 @@
// sleepFor1();
// setCurrentProgressStep(UpgradeProgressStep.VERIFYING);
// sleepFor1();
-// setCurrentProgressStep(UpgradeProgressStep.RECORDING_HISTORY);
-// sleepFor1();
+
+
} catch (ApplicationException ae) {
this.runException = ae;
@@ -404,6 +412,23 @@
try {
setCurrentProgressStep(UpgradeProgressStep.CLEANUP);
cleanup();
+
+ // Write a record in the log file indicating success/failure
+ setCurrentProgressStep(UpgradeProgressStep.RECORDING_HISTORY);
+ HistoricalRecord.Status status;
+ String note = null;
+ if (runException == null) {
+ status = HistoricalRecord.Status.SUCCESS;
+ } else {
+ status = HistoricalRecord.Status.FAILURE;
+ note = runException.getLocalizedMessage();
+ }
+ writeHistoricalRecord(historicalOperationId,
+ fromVersion,
+ toVersion,
+ status,
+ note);
+
} catch (ApplicationException e) {
System.err.print("error cleaning up after upgrade: " +
e.getLocalizedMessage());
@@ -419,6 +444,48 @@
}
+ private Long writeInitialHistoricalRecord(
+ Integer fromVersion,
+ Integer toVersion)
+ throws ApplicationException
+ {
+ Long id;
+ try {
+ HistoricalLog log =
+ new HistoricalLog(getInstallation().getHistoryLogFile());
+ id = log.append(fromVersion, toVersion,
+ HistoricalRecord.Status.STARTED, null);
+ } catch (IOException e) {
+ throw ApplicationException.createFileSystemException(
+ "error logging operation", e);
+ }
+ return id;
+ }
+
+ private void writeHistoricalRecord(
+ Long id,
+ Integer from,
+ Integer to,
+ HistoricalRecord.Status status,
+ String note)
+ throws ApplicationException {
+ try {
+ HistoricalLog log =
+ new HistoricalLog(getInstallation().getHistoryLogFile());
+ log.append(id, from, to, status, note);
+
+ // FOR TESTING
+ List<HistoricalRecord> records = log.getRecords();
+ for(HistoricalRecord record : records) {
+ System.out.println(record);
+ }
+
+ } catch (IOException e) {
+ throw ApplicationException.createFileSystemException(
+ "error logging operation", e);
+ }
+ }
+
private void upgradeComponents() throws ApplicationException {
try {
File stageDir = getStageDirectory();
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
index 18bbdf9..2ac5655 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
@@ -135,6 +135,25 @@
}
/**
+ * Creates a new file attempting to create the parent directories
+ * if necessary.
+ * @param f File to create
+ * @return boolean indicating whether the file was created; false otherwise
+ * @throws IOException if something goes wrong
+ */
+ public static boolean createFile(File f) throws IOException {
+ boolean success = false;
+ if (f != null) {
+ File parent = f.getParentFile();
+ if (!parent.exists()) {
+ parent.mkdirs();
+ }
+ success = f.createNewFile();
+ }
+ return success;
+ }
+
+ /**
* Returns the absolute path for the given parentPath and relativePath.
* @param parentPath the parent path.
* @param relativePath the relative path.
--
Gitblit v1.10.0