EmbeddedUpgradeProposal

From Epowiki

Jump to: navigation, search

This document discusses a design for an upgrade framework for a complex embedded system. The upgrade process refers to any required transformations between releases and artifacts of releases.

The design includes support for: newgrade, samegrade, downgrade, install, restore from factory, restore from backup, incremental data upgrade, and customer specific configuration. <P>

Contents

Introduction

This document discusses a design for an upgrade framework for complex embedded systems. The upgrade process refers to any required transformations between releases and artifacts of releases. <P>

The upgrade from an old release to a new release is an obvious example requiring transformations. Less obvious is the restoral of an older backup database to a new release. Even less obvious is the transformation of old data being written during an upgrade to the new release's format. All such transformations need support. <P>

The general idea is to:

  1. Have the upgrade process run in the new software release. Note, this isn't always possible for downgrade.
  2. Centralize upgrade code in a release manager.
  3. Provide an infrastructure for applications so their upgrade task is made obvious, simple, and robust.
  4. Support newgrade, samegrade, downgrade, install, restore from factory, restore from backup, and incremental data upgrade, and customer specific configuration.
  5. Prevent the errors we have seen during customer upgrades.
  6. Support upgrades between any two releases.

When applications start they will be guaranteed valid data. Applications will not have to perform implicit upgrades. This greatly simplifies applications and robustifies the upgrade process.


Motivation for Upgrade

Upgrade is a critical part of any system that often gets lost in the development cycle because there are always higher priorities. Unfortunately, your upgrade process is with you forever, so making a mistake dooms you to future pain if you don't approach it thoughtfully.

  1. Be able to upgrade from a release like 1.3.4 to 3.0 without intermediate upgrades. A customer would need, for example, to upgrade from 1.3.4 to 2.1 and then to 3.0. Given the sensitivity of upgrades customers are understandly not interested in performing multiple upgrades.
  2. Support downgrades. If a customer has upgraded, made new data, and then wants to move back a release, they can not do so unless the database is by accident compatible. The field has said customers would like to be able to perform downgrades.
  3. Upgrade restored backup images. Customers would like to use their new/old backups to get back to a known point.
  4. Runs upgrade in the context of the new release. Running an upgrade in an old release means the upgrade code has to be compiled against the old version to upgrade to the new version. It is then dynamically loaded. In practice this is too difficult to make work.
  5. Often there is a lot of upgrade code embedded in applications today. Upgrade would be more robust if we could isolate the implicit upgrade code and make it explicit.
  6. Support customer specific upgrades and installs.


Definitions

  1. current release. The currently running software release.
  2. data preserving. A data preserving upgrade is one in which new data is preserved during the upgrade. For example, if after newgrading between 2.1 to 3.0, the system runs for a while, and new data are in 3.0. Later it is desired to downgrade back to 2.1. If new data in 3.0 is preserved by reformating it to 2.1's format then it is a data preserving operation.
  3. downgrade. The upgrade from newer release to an older release. The major issue is if the process is data preserving. In a data preserving downgrade the release being downgraded from does not exist in the release manager's tables of the release being downgraded to. For example, when downgrading from 3.1 to 3.0, 3.0 does not know how to downgrade from 3.1. This means the dowgrade logic must be performed in the 3.1 release. This means the downgrade must be performed before the system reboots.
  4. fresh. A release in the same state as after an install. A newgrade is required to be in a fresh state.
  5. incremental data updgrade. The capability of being able to upgrade records not in the database on the fly. For example, records written during an upgrade process may need to be queued up until after the upgrade and then saved to the new release.
  6. install. A software release installed on to a system. It is not upgraded from another release.
  7. newgrade. The upgrade from an older release to a new release. Newgrades are by definition data preserving. Newgrades are always into a fresh release.
  8. new release. The release being upgraded to.
  9. new upgrade. A release using this new upgrade process.
  10. old release. The release being upgraded from. Usually the release currently running.
  11. old upgrade. A release using the old upgrade process.
  12. poor person's downgrade. See switch release.
  13. restore from backup. A release can have its data restored from a backup.
  14. restore from factory. A release can have its data restored from the factory database.
  15. samegrade. The upgrade to the same release of software. Often used during testing and development to load in new images. The change number must still be used to differentiate the releases.
  16. switch release. A release is switched to instead of being upgrade to. It is a non-data-preserving operation.
  17. upgrade. The process of changing from one release of software to another release. The term is used generically. Upgrade can mean newgrade, downgrade, or samegrade.
  18. version. Used to identify a software release. It has the form a.b.c.d.cnXXXX. All parts except the a are optional. All version numbers will be normalized to this format. A version specified as 2.0 will be changed to 2.0.0.0


Requirements

Necessary Requirements

  1. Be capable of upgrading any software version to any software version. This means supporting newgrades, samegrades, and downgrades. In practice, downgrades may not be fully supported. An important goal of this rule is to not have to perform multiple upgrades to move from one release to another.
  2. The upgrade process must be as simple, robust, and transparent as possible. It's easy to think of a lot of solutions that are complex enough to encourage errors in the field.
  3. The following capabilities must be supported: newgrade, samegrade, downgrade, install, restore from factory, restore from backup, and incremental data upgrade.
  4. The tables to be upgraded are determined by the new load and not the old load.
  5. Be able to ask the system if it can upgrade between two specified versions.
  6. Upgrade happens in the context of the new image. The upgrade software does not run in the old image.
  7. Running applications can not be necessary to perform an upgrade. At the time of the upgrade applications are not running.
  8. The upgrade system interfaces should be as database independent as possible so the upgrade logic can work across many versions.
  9. The same software version can always be upgraded to the same version.
  10. Output detailed diagnostic information during the process so problems can be more easily isolated.


Not Required

  1. Saving database updates during the upgrade process. The incremental data upgrade requirement will make this possible if and when it becomes a requirement.


Wouldn't it be Nice

  1. Think about how a new database would be handled. Note, by handle we are not talking at the application layer, this would remain the same, we are talking about in the file system layer, startup, etc.
  2. Think about how a new file system would be handled.
  3. General upgrade of things other than the database. There will be no problem adding more types of ugprade, but since it's not clear what these will be the topic will not be addressed in detail.
  4. Think about how the upgrade would be performed from a GUI.
  5. Determine if an upgrade is possible before rebooting to the new package.


What is Upgraded?

  1. Boot ROMS - The boot images on all cards are upgradeable, currently we do not upgrade them.
  2. Database - Currently the database is the only item upgraded from release to release.
  3. Bootstrap Config - Bootstrap configuration information.
  4. File System - The file system can be upgraded.

Software is not upgraded in the sense that it is not copied from the old release to the new release. Software is installed from scratch every time. <P>


Handling the Database

Types of Database Upgrades

  1. Accept New. Data in the new release is believed over the old release data.
  2. Merge. Data from the old release must be merged in to the new release.
  3. Update. Data from the old release must be modified before it is copied to the new release. Perhaps new fields must be added, types changed, or fields must be deleted.
  4. Accept Old. Data from the old release is believed so is copied without modification to the new release.
  5. Reorg. Reorg is more complicated change in the database. N tables may be merged into one. One table may be split into many tables.
  6. Drop Table. A table is being dropped from the old release in the new release.

In practice any combination of the above is possible. Strategies will change from release to release.


Order and Location of Updates

When data are being changed it is important to consider the order in which data are changed and where data are being changed. <P>

The old data should rarely if ever be changed during an upgrade. The reason is because we may have to rollback to that version. If the data had changed applications may no longer understand the new format. <P>

If, for example, there's a global change of an attribute type in many records in many tables, when and where should these changes be applied? Consider multiple changes will probably need to be applied to these records. <P>

If we apply the type changes before any other changes and write the changed records to the new release then we have created a big problem. Any other changes to be made would need to read from the new release before making their changes when in most cases they read only from the old release. We could make a copy of the data and make changes to the copy so all code will still think they are reading the old release. Copying data takes time. It will also be tricky to change the location of the old release directories. There's also the issue that applications will be operating with an object of a different format than they are used to. This is a general issue of when more than one change must be applied to a record. <P>

Consider the case where 3 tables are being merged into one. Would the type change be applied to records before the 3 tables were merged? If so would the records on disk need to change so the merge code could act like it was reading the records off disk? <P>

The goal then should be to perform all transforms in memory before writing a record to the new release.


Database Operations

This section discusses the operations applications should have available to them during the upgrade process. It's through these operations that applications perform the upgrade.

  1. Dropping a Table - This is implicitly supported. If a table is not marked as upgraded then it will not be copied to the new release.
  2. Get a Record from the Old/New Database
  3. Iterate Over all Old/New Records in a Table
  4. Add a Record to the New Database
  5. Delete a Record from the Old/New Database
  6. List All Tables in the Old/New Database
  7. The Count of Records in the Old/New Database
  8. Determine if a table is upgradeable in the Old/New Database.
  9. Dcraft and Debug Access - For example, it is desireable to have records dumped before and after transformations.


System Validation

Database operations will be validated to the extent possible. A record, for example, cannot be written to the new database if the specified table does not have a schema entry.


Release Manager Construction and Startup

This section provides an overview about how the ReleaseManager is constructed and how it starts in the system.

  1. A platform specific ReleaseManager, like XxxReleaseManager, is installed into the card's system state machine. It should be dependent on the GarbageCollector. The XxxReleaseManager installs itself as the singleton into ReleaseManagerService. ReleaseManagerService is in component/ReleaseManager.
  2. On construction, XxxReleaseManager constructs all the release specific SoftwareRelease objects for the release. Each software release will have its own SoftwareRelease object. The order in which releases are added is the order in which releases are related. Releases can not be compared simply by looking at the string. We might have classes named like SoftwareRelease300_Downgrade203_Newgrade301.
  3. On construction, each SoftwareRelease object creates the upgrade tables for performing a downgrade, samegrade, and newgrade. A SoftwareRelease knows where it fits in the release stream. That is, each SoftwareRelease is custom made. It knows what release it can downgrade to and what release it can newgrade to. These tables must be consulted to know if a downgrade or newgrade can be performed.
  4. The class TableUpgrade is the base class for implementing upgrade logic between releases. Each table in the release being upgraded to must have a TableUpgrade object installed for it. If a TableUpgrade doesn't exist then an upgrade can not be performed from the release in the desired direction. One can imagine many options for creating TableUpgrade objects. Base classes can be constructed that will do must of the work. It might be safest to create classes named like TableDowngrade_schema_300_to_203 so that no mistakes can be made.

General Approach - Upgrade (downgrade/newgrade/samegrade)

The section provides an overview of the upgrade part of the upgrade process. It provides the foundation for handling other parts of the upgrade process such as a restore from backup.

Upgrade Steps


  1. Step 1. The user downloads an software release package. Package is validated, load state set to upgrade, new boot image path is calculated.
  2. Step 2. The user performs the upgrade. UpgradePreReboot is called.
  3. Step 3. The user switches to the upgrade. This sets the boot image, sets load state to switching, and reboots.
  4. Step 4. The card reboots and goes to upgrade state. ReleaseManager performs the upgrade, says everything is ok and the card goes to primary.


Work is Performed in Upgrade State

After the install the system is rebooted to the new release. The new release goes to upgrade state. <P>

In upgrade state the ReleaseManager performs all the upgrade steps for the old and new releases. On a failure ReleaseManager asserts which should trigger the normal LMP rollback logic. <P>

On success ReleaseManager calls XxxSystem::UpgradePassed. UpgradePassed causes the transition UpgradeToInit and the regular card synchronization process takes over.


Maintain a List of All Releases

A list of all upgradeable releases is maintained in the CM image. For example, consider the following release stream: 1.3.4, 2.0.0, 2.0.3, 2.0.4, 2.1.0, 2.1A.2, 2.1A.3, 2.1.1, 2.1.3, 3.0. The list is maintained in the same order as they are added to the ReleaseManager. The version numbers themselves are not used to determine order. Using version numbers as the sort order would tie us to release names which are not predictable. <P>

The assumptions are:

  1. The entire release stream is linerizable.
  2. An upgrade can be made up of a pair-wise upgrade of every release between the old and new release.

An old release or new release not in this list can not be upgraded (except when they are the same version). The list must be updated with each release. Change numbers are supported in the version string. <P>

We can upgrade from 1.3.4 to 3.0 in one upgrade. Other approaches require staged upgrades. For example, 1.3.4 might have to upgrade to 2.1 which then would be upgraded to 3.0. <P>

We also have the structure for handling both upgrades and downgrades. <P>

One can think of a lot of different approaches, but the comprehensive version list has the advantage of being clear and hard to screw up. There are no wild cards or other intelligence in the process. <P>

Release Related Operations

A release has an interface (see class SoftwareRelease) whos responsibility is to abstract the differences between releases.

  1. DbApplication. Abstracts the low level database interface for the version. Applications need to have access to the low level database in-order to perform their database transformations. The DbApplication is an attempt to isolate the differences between database versions in the event the database is changed.
  2. DbManager. Abstracts the high level database interface.
  3. UpgradePreReboot. Called during an upgrade, on the old release, before the reboot to the new version occurs. It might, for example, copy the System.lnp from the current release to the new release.
  4. InstalledNewgradeDbSetup. Called before the database transformation steps are called to do any preparation work. There is also InstalledDowngradeDbSetup. Installed methods are called for releases that are installed on disk.
  5. InstalledNewgradeDbTeardown. Called after the database transformation steps have been called to do any cleanup work. It may, for example, rebuild indexes. There is also InstalledDowngradeDbTeardown.
  6. GhostNewgradeDbSetup. Called before the database transformation steps are called to do any preperation work. Ghost methods are called for releases not installed on disk.
  7. GhostNewgradeDbTeardown. Called after the database transformation steps have been called to do any cleanup work.


Define Strategies for each Table for each Release

Notice that most releases will not be on disk. The implication is that the schema can not be read to determine if a table should be upgraded. The further implication is that an explicit list of tables is required to know how to handle the upgrade for tables in releases not stored on disk. <P>

Every database table in a release needs a description of how the table is upgraded from the previous release. The new release knows how to upgrade from the old release. <P>

When upgrading from 2.2 to 3.0, for example, the 3.0 table description specifies how the tables in 3.0 are created from the data in 2.2. For example, table AAA in 3.0 may be created from 2 tables in 2.2. The strategies installed for AAA in 3.0 would know how to perform this transformation. <P>

When downgrading from 3.0 to 2.2, for example, the 2.2 table description specifies how the tables in 2.2 are created from data in 3.0. <P>

The algorithm for a samegrade is discussed later. <P>


Table Strategies

The following strategies can be defined for the newgrade, downgrade, samegrade, and custom configuration of a table:

  1. Read. A list of transformations that are applied when a record is read from the old release. The PortId transform, for example, can be applied whenever the record is read. This means the application upgrade code is seeing the already transformed record.
  2. Write. A list of transformations that are applied when a record is written to the new release. The PortId transform, for example, can be applied whenever the record is written. This means the application upgrade code is seeing the old record.
  3. Table Transform. A transformation applied to a table. The transform is responsible for reading all the old records and writing the new records. The Read and Write strategies are a good place to put changes that can be applied by the "driver" transform.
  4. Validation. A method that is called to determine if data in a table is valid.


Standard Strategies

A set of standard transform strategies are available:

  1. AcceptNew. This means the new table overrides the old table. No data are copied.
  2. AcceptOld. Copy the old data to the new release. The Read and Write transforms are performed. This means AcceptOld can be used as a driver to iterate through all the records in a table and the Read and Write transforms can be used to perform the appropriate transforms.
  3. ReplaceWithOld. If there are existing records in the new release then delete them. Then perform like AcceptOld.
  4. DropTable. The table is being dropped in the new release.
  5. TableIsNew. The table is new in this release and has no corresponding table in the old release.


Upgrade Code Access

Upgrade code has access to the old and new database within each strategy. Using this access applications perform the upgrade of their tables.


Knowing the Old Revision

The image to rollback to is stored in a boot table. When running under the new image the old version is derivable from the rollback image. Why this matters is the upgrade process must know which version it is upgrading from. <P>

The old version should be put in System early the boot process before upgrade occurs. <P>


Basic Newgrade/Downgrade Algorithm

  1. Find the release with the old version number. If it can't be found the upgrade can't happen. If it is not on disk then the upgrade can't happen because there would be no data to upgrade.
  2. Find the release with the new version number. If it can't be found the upgrade can't happen.
  3. If the version numbers have change numbers and there are no corresponding version numbers with change numbers in the release list and the version numbers are the same then perform a samegrade upgrade.
  4. If the old version number is less than the new version number then it is an newgrade. If the old version number is greater than the new version number it is a downgrade. The choice of newgrade or downgrade determines which set of strategies to use. Remember that order is determined by the order SoftwareRelease objects are added to the ReleaseManager, not by comparing version numbers.
  5. In a pair-wise fashion traverse every release between the old and new release and perform the upgrade functions.
  6. Intermediate releases, between the old and new release, that happen to be installed on disk, are totally ignored. Data from the old release are transformed to the format for the new release. The upgrade matrix is the sole source for how these data transforms are performed. The on disk installations are not consulted.


Samegrade Algorithm

It is very convenient for testing and development to support the upgrading of the same version to the same version. Rather than specify strategies for a samegrade, perhaps the following algorithm will work:

  1. If a table in the new release has data then don't copy data from the old release. This will stop tables like schema and CMD from being overwritten.
  2. If a table in the new release does not have data and the old release has data then copy data from the old release to the new release. Tables like AAA will be copied. A lot of other tables will be copied that don't need to be copied, but that's life.


Add Upgrade Matrix to Install Package

There's a chicken-egg problem in knowing if a new release can be upgraded to. The old release doesn't know about the new release so the old release doesn't know if it can be upgraded to the new release. The new release isn't running yet so we can't ask it if the upgrade is supported. <P>

We could install the new release, boot it, and then rollback if the upgrade isn't supported. While this would work there's a lot of bad things that can happen on the way just to be able to verify if an upgrade can happen. <P>

Instead, a version of the upgrade matrix is in the install package descriptor. This allows the install package to be uploaded, the descriptor extracted, and then the old release can use the matrix to verify if the new release can be upgraded. <P>

Older releases will not be able to make this check so we will still need to check on the full install.


Handling Local and Private Branch Builds

Local and private branch releases should not be in the master version list. They are primarily upgrading to the same version of software, which is covered by samegrade functionality.

Handling Feature Branches

Any branch can specify their version number, so it's possible to test upgrade logic.


Customer Specific Upgrades

See Custom Configuration. A customer can be considered one a custom configurable parameter.


Handling Newgrade/Downgrade with Data

It is possible to specify a newgrade to an already installed release that has data. For example, an upgrade happens to 3.0, which runs for a while and accumulates new data. Then a downgrade happens to 2.1.0. Then an upgrade happens again from 2.1.0 to 3.0. The problem is 3.0 has data. So what should happen? Should we merge data between the releases? There is not current requirement to support this capability so it would be better not to add more complexity into the system. <P>

Instead, the rule when doing a newgrade into a release with data is to make the new release fresh. This means restore the factory database so the normal newgrade logic can be used and we don't need to worry about merging.


General Approach - Install

The section provides an overview of the install part of the upgrade process. <P>

The open question is when should PerformInstall be called? Need an answer to what is happening during the install system state. Options are swload to install. Could put a file in the release as a trigger.

Customer Specific Installs

See Custom Configuration. A customer can be considered one a custom configurable parameter.


General Approach - Restore from Factory

The custom configuration needs to be activated as the factory database isn't customer specific. Otherwise, TBD. <P>


General Approach - Restore from Backup

A restore may be happening from either an older or newer release. The backup file contains the software release it was made from. <P>

The goal is to setup the structure so a normal upgrade process can be used. The current release is treated as the new release. The backup file is untarred to a temporary directory and is treated as the old release. <P>

ReleaseManager::PerformRestoral is called to perform the restoral. Newgrade and downgrade can be performed normally. A samegrade must be handled specially as the goal is replace the existing database with the restored database. If a samegrade was applied then a merge of the databases would occur. DbManager::ReplaceDatabase is called to perform the restoral function. <P>



General Approach - Incremental Data Upgrade

TBD


Custom Configuration

Custom configuration allows a NE configuration to be site specific. Currently we ship the same database to every customer. Sometimes we want a customer to have a different set of defaults (login banner, alarm mappings, threshold settings, etc). <P>


Specifying Custom Configurations

A thought is that custom configuration selections are set in the initial configuration as it can change everything. Then the options would be available from System. <P>

The ReleaseManager reads the options from System and ignores transforms configured for specific options unless they are in the current set of options. By default there are no options. <P>

Custom Configuration is NE Wide


Has Own Transform Table

Custom configuration has its own transform table in the SoftwareRelease object. This allows custom configuration to be controlled separately and be applied when necessary. Custom configuration transforms would be applied during an upgrade, install, or restore from factory, but would not be applied during a restore from backup. <P>

Targeted Transforms

Read, Write, and Table transforms can be targeted at specific custom configurations. <P>


Implementation Notes

Software Structure

The ReleaseManager is usable across products. This means the ReleaseManager should have a common reusable core with a product specific configuration. <P>

All the upgrade related software will be in the same directory (XxxReleaseManager). Specialized application libraries should not be necessary as applications can code soley in terms of the interfaces provided by the upgrade library. <P>

/component/ReleaseManager

Contains common reusable ReleaseManager core. It includes the system module/actor. The SoftwareRelease instances and factories are added in later.

/xxx/component/XxxReleaseManager

Used by all products. Every release creates a SoftwareRelease class. The XxxReleaseManager instantiates and inserts every SoftwareRelease on construction. The SoftwareRelease objects in-turn build up their configuration of table upgrades. Each TableUpgrade is its own class and could be used by multiple SoftwareReleases. <P>

Common classes can be created as needed to be shared among releases.

System State Machine

The ReleaseManager will have to be in the upgrade transition in the system state machine on a node.


Class Interfaces

This section presents some very preliminary class iterfaces. They are more suggestive than prescriptive.


Class ReleaseManager

/**
 * ReleaseManager is the interface to software releases.
 */
class ReleaseManager
{
public:

    /**
     * The direction of the upgrade.
     */
    typedef enum UpgradeDirection
    {
       UPGRADE_NEWGRADE,
       UPGRADE_SAMEGRADE,
       UPGRADE_DOWNGRADE
    };


     /** 
      * Determine if an upgrade is possible using the upgrade matrix compiled into
      * the program. 
      */ 
     LnStatus          IsCanUpgrade(
                         UpgradeDirection& rDirection,
                         VersionNumber newVersion, 
                         VersionNumber oldVersion);


     /** 
      * Determine if an upgrade is possible using the upgrade matrix compiled into
      * the program.
      */ 
     LnStatus          IsCanUpgrade(
                         VersionNumber newVersion, 
                         VersionNumber oldVersion);


     SoftwareRelease*  GetRelease(VersionNumber version);
     SoftwareRelease   GetNextRelease(VersionNumber version);
     SoftwareRelease   GetPreviousRelease(VersionNumber version);
     SoftwareRelease*  GetCurrentlyRunningRelease();

     /**
      * Add a release. Order is important as the order determines the order
      * in which releases are a searched.
      */
     LnStatus          AddRelease(SoftwareRelease* pRelease);


     /**
      * Perform the upgrade between the two versions. It may be a downgrade,
      * newgrade, or samegrade.
      */
     LnStatus          PerformUpgrade(
                         VersionNumber newVersion, 
                         VersionNumber oldVersion);

     /**
      * Perform the upgrade given a path to an install image. It takes
      * all necessary steps.  The ReleaseManager is responsible for unpacking 
      * the image, deleting the image, managing the load states, etc.
      * See StartUpgradeFromInstallImage, ExectuteUpgradeFromInstallImage,
      * SwitchToUpgradeFromInstallImage.
      */
     LnStatus          PerformUpgradeFromInstallImage(const char* pFpathToInstallImage);

     /**
      * Start the upgrade given a path to an install image.  Supports CLI menu item 7.
      */
     LnStatus          StartUpgradeFromInstallImage(const char* pFpathToInstallImage);


     /**
      * Perform the upgrade steps necessary for the upgrade. Supports CLI menu item 8.
      * For a downgrade much of the logic is performed here. For a newgrade/samegrade
      * the logic will happen after the reboot.
      */
     LnStatus          ExecuteUpgradeFromInstallImage();


     /**
      * Switches to the upgrade. Supports CLI menu item 9.
      */ 
      LnStatus         SwitchToUpgradeFromInstallImage();

     /**
      */
     LnStatus          PerformInstall(VersionNumber version);

     /**
      */
     LnStatus          PerformRestoral(
                         VersionNumber newVersion, 
                         const LnTar&  backup);


     void	              InstallEnvAdapter(ReleasManagerEnv*);
     const ReleaseManagerEnv* GetEnvAdapter() const

     /**
      * After an upgrade process has run there is garbage collection
      * that needs to happen. GarbageCollection on all software releases 
      * is performed. 
      */
     LnStatus     GarbageCollect();
};


Class ReleaseManagerService

/**
 * ReleaseManagerService is the singleton interface for the card. It is
 * set with the platform specific ReleaseManager.
 */
class ReleaseManagerService
{
}


Class XxxReleaseManager

/**
 * XxxReleaseManager is an implementation of a ReleaseManager for
 * the the CD and CI. It must set itself into ReleaseManagerService.
 */
class XxxReleaseManager : public ReleaseManager
{
};


Class DbManager

/**
 * DbManager abstracts a higher level application level database for use
 * particular software release. It contains the operations applications 
 * can use to upgrade from one release to another.
 */
class DbManager
{
    /**
     * Take whatever steps are necessary to reinitialize the database
     * to an installed state.
     */
    virutal LnStatus MakeFresh() = 0;

    /**
     * Has the database been used?
     */
    virutal bool     IsNotFresh() = 0;


    /**
     * Move the database to a temporary area so it can be
     * upgraded to. It must be done in such a way that
     * a reboot can not cause an empty database to be
     * asserted.
     */
   virtual LnStatus  MoveToTemporaryArea() = 0;


    /**
     * Move the temporary database the actual database.
     */
   virtual LnStatus  MakeTemporaryDataTheActualData() = 0;


    /**
     * Garbage collect the temporary database. 
     */
   virtual LnStatus  GarbageCollectTemporaryData() = 0;


    /**
     * Replace the current database with a new database.
     */
   virtual LnStatus  ReplaceDatabase(const char* pPath) = 0;

};


Class DbApplication

/**
 * DbApplication abstracts the application level database for a 
 * particular software release. It contains the operations applications 
 * can use to upgrade from one release to another.
 */
class DbApplication
{
public:
     /**
      * Any read transforms are applied before the record is returned.
      */
     Properties*  GetRecord(const char* pTable, const char* pPrimaryKey);
     bool         IsRecordExist(const char* pTable, const char* pPrimaryKey);
     Properties*  DeleteRecord(const char* pTable, const char* pPrimaryKey);

     uint32       GetRecordCount(const char* pTable);

     /**
      * Any write transforms are applied before the record is written.
      */
     LnStatus     AddReplaceRecord(Properties* pRecord);

     LnStatus     DeleteTable(const char* pTable);
     LnStatus     DeleteAllRecords(const char* pTable);
     bool         IsTableExist(const char* pTable);

     DbTableIter* CreateTableIter();

     LnStatus     CopyTable(
                      const char*  pFromTable, 
                      DbApplication& rToDatabase, 
                      RecordXform* pXform=0);

};


Class PsDbManager

/**
 * PsDbManager is the DbManager interface for Ps.
 */
class PsDbManager : public DbManager
{
    /**
     * Restore from the factory database. Clear anchor files.
     */
    virutal LnStatus MakeFresh();

    /**
     * Look at the anchor files to determine if any data have been
     * saved. 
     */
    virutal bool     IsNotFresh();


    /**
     * Rename the data directory for the release to a temporary directory.
     * If a reboot happens and the data directory is not present
     * then the system will ask to restore a backup.
     */
   virtual LnStatus  MoveToTemporaryArea();


   /**
    * Rename the temporary directory back to the data directory.
    */
   virtual LnStatus  MakeTemporaryDataTheActualData();


    /**
     * The temporary directory is deleted in place. In the future we may
     * not have big enough disks to keep temporary directories around, so
     * they need to be deleted immediately.
     */
   virtual LnStatus  GarbageCollectTemporaryData();


    /**
     * Replace the current database with a new database.
     */
   virtual LnStatus  ReplaceDatabase(const char* pPath);

}


Class PsDbApplication

/**
 * PsDbApplication is the DbApplication interface for Ps.
 */
class PsDbApplication : public DbApplication
{

}


Class SoftwareRelease

/**
 * SoftwareRelease represents an official release of software that must
 * be supported.
 */
class SoftwareRelease
{
public:
     enum UpgradeType
     {
         TYPE1_UPGRADE_TYPE,  /* pre initial release */
         TYPE2_UPGRADE_TYPE,  /* post initial release */
     };

     VersionNumber  GetVersion();

     bool         IsCurrentlyIntalledOnDisk();

    /**
     * Is the release freshly installed or has it been used?
     */
     bool         IsNotFresh();

     UpgradeType  GetUpgradeType();

     LnStatus     ValidatePackage();

     LnStatus     SetBootImage();

     /**
      * These provide low level database access to the upgrade code.
      * Have to decide if these are static or dynmically created.
      */
     DbApplication* CreateDbApplication();
     DbManager*   CreateDbManager();

     Properties*  GetSystemLnp();

     LnStatus     WriteSystemLnp(Properties& rSystemLnp);

     /**
      * After an upgrade process has run there is garbage collection
      * that needs to happen. The software release must reset any
      * state related to a particular upgrade. For example, database
      * path name and any temporary directories that were created.
      */
     LnStatus     GarbageCollect();


     LnStatus     NewgradePerform(SoftwareRelease& rOldVersion);
     LnStatus     DowngradePerform(SoftwareRelease& rOldVersion);
     LnStatus     SamegradePerform(SoftwareRelease& rOldVersion);

     LnStatus     UpgradePreReboot(const char* pNewVersionDpath);

     /**
      * Called when a upgrade has been completed successfully.
      * GarbageCollect is called.  ReleaseManagerEnv::ContinueWithUpgrade
      * called.
      */
     LnStatus     UpgradeCompleted();

    /**
     * Take whatever steps are necessary to reinitialize the release
     * to an installed state.
     */
     LnStatus     MakeFresh();

     LnStatus     InstalledNewgradeDbSetup(SoftwareRelease& rOldVersion);
     LnStatus     InstalledNewgradeDbTeardown(SoftwareRelease& rOldVersion);

     LnStatus     GhostNewgradeDbSetup(SoftwareRelease& rOldVersion);
     LnStatus     GhostNewgradeDbTeardown(SoftwareRelease& rOldVersion);

     LnStatus     InstalledDowngradeDbSetup(SoftwareRelease& rOldVersion);
     LnStatus     InstalledDowngradeDbTeardown(SoftwareRelease& rOldVersion);

     LnStatus     GhostDowngradeDbSetup(SoftwareRelease& rOldVersion);
     LnStatus     GhostDowngradeDbTeardown(SoftwareRelease& rOldVersion);
 
     LnStatus     AddTableNewgrade(TableNewgrade* pUpgrade);
     Properties*  GetTableNewgradeList();

     LnStatus     AddTableDowngrade(TableDowngrade* pUpgrade);
     Properties*  GetTableDowngradeList();

     LnStatus     AddTableSamegrade(TableSamegrade* pUpgrade);
     Properties*  GetTableSamegradeList();

     LnStatus     AddTableCustomConfiguration(TableCustomConfiguration* pUpgrade);
     Properties*  GetTableCustomConfigurationList();

     /**
      * High level determination of a downgrade or newgrade can proceed.
      * It just doesn't take into account the database upgrade process,
      * but all other items that can be upgraded.
      */
     bool         IsCanDowngrade(SoftwareRelease& rOldVerion);
     bool         IsCanNewgrade(SoftwareRelease& rOldVerion);
};


TableUpgrade

/**
 * TableUpgrade represents how a table should be upgraded from an
 * old release a new release. The upgrade may be a newgrade or downgrade.
 */
class TableUpgrade
{
public:
    RWCString	      GetTableName();

    Properties*       GetOldTablesAccessed();
    Properties*       GetNewTablesAccessed();
    const char*       GetDescription();

    RecordTransform[[ | ]] pReadTransforms;
    RecordTransform[[ | ]] pWriteTransforms;
    TableTransform*   pTableTransform;
    TableValidator*   pValidator;
};


TableNewgrade

/**
 * TableNewgrade is an upgrade for upgrading from an old to new
 * release.
 */
class TableNewgrade : public TableUpgrade
{
public:
};


TableDowngrade

/**
 * TableDowngrade is an upgrade for upgrading from a new to old
 * release.
 */
class TableDowngrade : public TableUpgrade
{
public:
};


TableSamegrade

/**
 * TableSamegrade is an upgrade for upgrading from between the same
 * releases.
 */
class TableSamegrade : public TableUpgrade
{
public:
};


TableCustomConfiguration

/**
 * TableCustomConfiguration is an upgrade for custom configuration.
 */
class TableCustomConfiguration : public TableUpgrade
{
public:
};


RecordTransform

/**
 * Transform the structure or values of a record.
 */
class RecordTransform 
{
public:
     /**
      * A transform can be targeted at a specific custome configuration. 
      * By default the name is empty which means it as applied to every
      * record.
      */
     const RWCString&		GetTargetConfigurationName() const;

     bool TransformRecord(
       SoftwareRelease& rOldRelease,
       SoftwareRelease& rNewRelease);
       Properties&      rRecordToTransform);
};


TableTransform

/**
 * Transform a table in the new release from table(s) in the old
 * release.
 */
class TableTransform 
{
public:
     /**
      * A transform can be targeted at a specific custom configuration. 
      * By default the name is empty which means it as applied to every
      * record.
      */
     const RWCString&		GetTargetConfigurationName() const;
 
     LnStatus TransformTable(
         SoftwareRelease& rOldRelease,
         SoftwareRelease& rNewRelease);
};


Class ReleaseManagerEnv

/**
 * ReleaseManagerEnv is an adapter between platform specific services
 * and the generic ReleaseManager functionality.
 */
class ReleaseManagerEnv
{
public:
      virtual LnStatus ContinueWithUpgrade() = 0;
      virtual LnStatus SetLoadState(const char* pLoadState) = 0;
};


Classes for Standard Strategies

There will classes implementing standard TableUpgrade and TableTransform objects.


Scenarios

This section discusses scenarios new upgrade should support. It is incomplete because it primarily focusses on downgrade/newgrade/samegrade.

Specific Scenarios

Most of the scearios need more work.

Upgrading Using Unknown Releases

Either the old or new release does not exist in the ReleaseManager. The exception is a samegrade upgrade which should always be handled.


Upgrading Non-Existent Releases

Either the old or new release does not exist on disk. Both must exist on disk for the upgrade to proceed.


Upgrading from Old Release to New Release

The upgrade is from an old to a new release. There are no intermediate releases.


Upgrade From Old Upgrade to New Upgrade

Upgrade from a release using the old upgrade process to a release using the new release process.


Upgrading from Old to New with One Intermediate Releases

The upgrade is from the old to new release with one intermediate release.


Upgrading from Old to New with Two Intermediate Releases

The upgrade is from the old to new release with two intermediate release.


Upgrade With Read Transforms


Upgrade With Write Transforms


Upgrade With Read and Write Transforms


Upgrade With Table Transforms


Upgrade With Default Transforms


Upgrade With Dropping Tables


Upgrade With Adding Tables


Upgrade With Recombining Tables


Upgrade With Global Changes


Abort Upgrade


Samegrade Upgrade Without Change Numbers

Upgrade to same version. The version numbers do not contain change numbers.


Samegrade Upgrade With Change Numbers

The version numbers do contain change numbers.


Restored Backup Scenarios

The same as the upgrade scenarios. Instead of an old release being the source of data, the backup file is the source of data.


Custom Configuration for Upgrade/Install


Example Software Release Matrix

This release matrix is made up to test the previous scenarios. The matrix is not complete nor does it reflect reality, it's used only for testing the upgrade feature.

  1. 1.3.4. This is the first software release in this list. It cannot be upgraded to. Has tables schema, AAA, BBB. and FOO.
  2. 2.0.0. Knows how to upgrade from 1.3.4.
    1. Has tables schema, AAA, and BBB.
    2. Schema is AcceptNew, so it is not copied.
    3. AAA is AcceptOld, so it is copied.
    4. BBB is AcceptOld so it is copied.
    5. All PortIds must be changed to a new type so a Read transform is applied to all tables. A Write transform could have been used as well, it just depends what format you want the application to see in its record transform. Since the defuault AcceptOld table transform is being used it doesn't matter as AcceptOld just passes the records through.
    6. Table FOO is being dropped so it is DropTable.
  3. 2.0.3. Knows how to upgrade from 2.0.0.
    1. Has tables schema, AAA, BBB, CCC, CCC1, CCC2.
    2. Schema is AcceptNew, so it is not copied.
    3. AAA is AcceptOld, so it is copied.
    4. BBB is AcceptOld so it is copied. BBB, however, wants to change all its file names. So BBB adds a Write filter which changes the primary key name of the record. As the primary key is the file name the file name has been changed.
    5. CCC, CCC1, CCC2 are new tables so they have TableIsNew.
  4. 3.0. Knows how to upgrade from 2.0.3.
    1. Has tables schema, AAA, BBB, CCC, ManagementObject.
    2. Schema is AcceptNew, so it is not copied.
    3. AAA is AcceptOld, so it is copied.
    4. BBB is AcceptOld so it is copied.
    5. ManagementObject is a new table so it is AcceptNew.
    6. CCC is being combined from CCC1 and CCC2. CCC has a table transform that iterates through CCCs, reads the appropriate CCC1 and CCC2 records, and the writes out a new CCC record. CCC1 and CCC2 are DropTable because they are being dropped in favor of a single CCC table.
    7. The login banner is customer specific. The login banner table has a customer specific table transform.
  5. 3.1. Knows how to upgrade from 3.0.
    1. Has tables schema, AAA, BBB, CCC, ManagementObject.
    2. Schema is AcceptNew, so it is not copied.
    3. BBB is AcceptOld so it is copied.
    4. AAA is AcceptOld, so it is copied.
    5. CCC is AcceptOld, so it is copied.
    6. ManagementObject must merge the custom defaults from old into the new release. ManagementObject makes a table transform the loops through all the old descriptors, looks up the corresponding new descriptor, merges in the custom defaults, and then writes the new descriptor.
  6. 2.0.3. Knows how to downgrade from 3.0.
    1. Has tables schema, AAA, BBB, CCC, CCC1, CCC2.
    2. Schema is AcceptNew, so it is not copied.
    3. AAA is ReplaceWithOld, so it replaces.
    4. BBB is ReplaceWithOld so it repleaces.
    5. ManagementObject is DropTable because it doesn't exist in 2.0.3.
    6. CCC must be broken out to create CCC1 and CCC2.


General Walkthrough

  1. The ReleaseManager has been created and installed into the system state machine. The ReleaseManagerEnv has been installed into the ReleaseManager. The platform specific ReleaseManager has been installed into the ReleaseManagerService singleton.
  2. Upgrade is started via the CLI.
    1. Install package is copied to a file in the temp directory. This is important so it will get deleted on a failure.
    2. The CLI calls ReleaseManager::StartUpgradeFromInstallImage.
    3. The ReleaseManager unpacks the install image to a temp area.
    4. The install image is deleted.
    5. The package is validated.
    6. It is determined if the upgrade can be performed. If the upgrade can't be performed the directory is deleted. The CLI gets an exception telling them what went wrong. Note, for a newgrade this can only be determined if the install package has an upgrade matrix. A downgrade and samegrade can be determined using the currently running image.
    7. Load state is set to upgrade (via the ReleaseManagerEnv).
    8. New boot image is calculated.
    9. The directory is renamed to be the package directory.
    10. Call UpgradePreReboot (copies the System.lnp file).
  3. Then the CLI executes the upgrade:
    1. The CLI calls ReleaseManager::ExecuteUpgradeFromInstallImage.
    2. If a newgrade/samegrade is needed then the upgrade steps will be delayed so they can operate in the new release.
    3. If a downgrade is needed then the downgrade steps are peformed in the context of the current release.
      1. Every SoftwareRevision pair between the old and new version is visited. For every pair call DowngradePerform on the new release:
        1. Call InstalledDowngradeDbSetup or GhostDowngradeSetup.
        2. Excute the TableUpgrade for each table. Which table list to use depends on the upgrade direction.
        3. Call InstalledDowngradeDbTeardown or GhostDowngradeDbTeardown.
      2. ReleaseManager::UpgradeCompleted is called. Garbage collection happens.
  4. Then the CLI switches to the upgrade:
    1. The CLI calls ReleaseManager::SwitchUpgradeFromInstallImage.
    2. Sets the boot image.
    3. Sets the load state to switching.
    4. Reboots.
  5. System boots using the new image. It transitions to upgrade state. The ReleaseManager transition to upgrade is triggered.
  6. The old release is extracted from System.
  7. The new release is extracted from System.
  8. ReleaseManager::PerformUpgrade is called.
  9. If the old release uses an old upgrade then take steps to reverse out the old upgrade process. SoftwareRelease::MakeFresh should do this. See Upgrading Old Upgrade to New Upgrade.
  10. If the new release is not fresh then SoftwareRelease::MakeFresh is called.
  11. If a downgrade needs to be performed:
    1. The old release will not be in the release manager's table. If this happens we assume a downgrade.
    2. It was already performed in the previous release so nothing needs to be done. Call ReleaseManager::UpgradeCompleted.
  12. If a newgrade/samegrade needs to be performed:
    1. Every SoftwareRevision pair between the old and new version is visited. The direction of upgrade has been determined using IsCanUpgrade. The direction determines which methods are called. <P> For every pair call NewgradePerform/SamegradePerform on the new release:
      1. Call InstalledNewgradeDbSetup or GhostNewgradeDbSetup.
      2. Excute the TableUpgrade for each table. Which table list to use depends on the upgrade direction.
      3. Call InstalledNewgradeDbTeardown or GhostNewgradeDbTeardown.
    2. ReleaseManager::UpgradeCompleted is called. Garbage collection happens. The upgrade process continues. Through normal LMP channels the secondary will reboot and the rest of the system will sync with the upgraded image.

<P>

The ghost versions of methods are called on releases between the old and new release. They will create a temporary directory for performing the upgrade operations. These temporary directories must be deleted immediately after they become unecessary.


Scenario Newgrade Between 1.3.4 - 3.0

The scenario starts where the ReleaseManager has transitioned to upgrade. Note, the upgrade is performed in a pair-wise fashion between all releases found between 1.3.4 - 3.0. No reboot occurs between release pairs. <P>

Release 1.3.4 is the old release and exists on disk. 3.0 is the new release and it also exists on disk because it was installed. <P>


1.3.4 to 2.0.0

The first pair of upgrades is 1.3.4 to 2.0.0.

  1. The 1.3.4 release is found by asking the ReleaseManager. The 2.0.0 release is found by asking the ReleaseManager for the next release after 1.3.4.
  2. By asking the SoftwareRelease it is determined that 1.3.4 used an old upgrade process so the new release must reverse the old upgrade before proceeding.
  3. NewgradePerform on release 2.0.0 is called.
  4. NewgradePerform calls GhostNewgradeDbSetup because 2.0.0 is not the old release and its not the new release.
  5. GhostNewgradeDbSetup creates a temporary directory for storing the upgraded data from 1.3.4. The directory will be C:\temp\2.0.0data. This is the path used for the new database. The old database is the real database in 1.3.4. The temporary directory is created using DbManager::MoveToTemporaryArea.
  6. Then the new TableUpgrade list is walked through. Schema is found first and AcceptNew is executed. It does nothing so the new schema stays intact.
  7. AAA is found next and AcceptOld is executed. Accept old loops through all records in the old database and writes them to the new database. There's a Read filter for handling new port IDs. The filter is applied before the record is given to AcceptOld.
  8. BBB is found next is handled the same as AAA.
  9. No entry exists for FOO in 2.0.0 so it is dropped.

Now we have a directory that has all the upgraded data from 1.3.4.


2.0.0 to 2.0.3

The next pair of upgrades is 2.0.0 to 2.0.3.

  1. We already have the 2.0.0 release. The 2.0.3 release is found by asking the ReleaseManager for the next release after 2.0.0.
  2. NewgradePerform on release 2.0.3 is called.
  3. NewgradePerform calls GhostNewgradeDbSetup because 2.0.3 is not the old release and its not the new release.
  4. GhostNewgradeDbSetup creates a temporary directory for storing the upgraded data from 2.0.0. The directory will be C:\temp\2.0.3data. This is the path used for the new database. The old database is 2.0.0data. The temporary directory is created using DbManager::MoveToTemporaryArea.
  5. Then newgrade TableUpgrade list is invoked. Schema is found first and AcceptNew is executed. It does nothining so the new schema stays intact.
  6. AAA is found next and AcceptOld is executed. Accept old loops through all records in the old database and writes them to the new database.
  7. BBB is found next AcceptOld is executed. BBB has a write transform so it can change all its filenames. When AcceptOld writes the record to the new database it applies the Write transform.
  8. CCC, CCC1, CCC2 are new tables so they use AcceptNew, which does nothing.
  9. Delete temporary directory.

Now we have a directory that has all the upgraded data from 2.0.0.


2.0.3 to 3.0.0

The next pair of upgrades is 2.0.3 to 3.0.0.

  1. We already have the 2.0.3 release. The 3.0.0 release is found by asking the ReleaseManager for the next release after 2.0.3.
  2. NewgradePerform on release 3.0.0 is called.
  3. NewgradePerform calls InstalledNewgradeDbSetup because 3.0.0 is the new release.
  4. InstalledNewgradeDbSetup renames the data directory in the release to C:\temp\3.0.0data. The reason we do this is so a reboot in the middle of the upgrade will not cause inconsistent data to be used. The old database is 2.0.3data. The temporary directory is created using DbManager::MoveToTemporaryArea.
  5. Then TableUpgrade list is walked through. Schema is found first and AcceptNew is executed. It does nothining so the new schema stays intact.
  6. AAA is found next and AcceptOld is executed.
  7. BBB is found next AcceptOld is executed.
  8. CCC has a table transform to merge the CCC, CCC1, and CCC2 tables together. CCC loops through all the old CCC record. For each CCC record it gets and merges in the corresponding CCC1 and CCC2 records. The new CCC record is written to the new database.
  9. InstalledNewgradeDbTeardown is called to rename 3.0.0data back to data using DbManager::MakeTemporaryDataTheActualData.
  10. ReleaseManager::PerformUpgrade notices that the new release has been upgraded. ReleaseManager::UpgradeCompleted is called.
  11. Delete temporary directory.


Scenario Newgrade Between 3.0.0 - 3.1.0

The scenario starts where the ReleaseManager has transitioned to upgrade. If the new release is not a fresh install the upgrade will abort. <P>

Release 3.0.0 is the old release and exists on disk. 3.1 is the new release and it also exists on disk because it was installed. <P>

  1. Ask the ReleaseManager for 3.0.0. The 3.0.1 release is found by asking the ReleaseManager for the next release after 3.0.0.
  2. NewgradePerform on release 3.0.1 is called.
  3. NewgradePerform calls InstalledNewgradeDbSetup because 3.0.1 is the new release.
  4. InstalledNewgradeDbSetup renames the data directory in the release to C:\temp\3.0.1data. The reason we do this is so a reboot in the middle of the upgrade will not cause inconsistent data to be used. The old database is the real database in 3.0.0. The temporary directory is created using DbManager::MoveToTemporaryArea.
  5. Then TableUpgrade list is walked through. Schema is found first and AcceptNew is executed. It does nothining so the new schema stays intact.
  6. AAA, BBB, and CCC are all AcceptOld.
  7. ManagementObject has a table transform to custom defaults from old into the new release. The table transform the loops through all the old descriptors, looks up the corresponding new descriptor, merges in the custom defaults, and then writes the new descriptor. Any new descriptors remain untouched. Any descriptors that have been dropped in the new release may be be ignored or perhaps special merge log is needed to save the data.
  8. InstalledNewgradeDbTeardown is called to rename 3.0.1data back to data.
  9. ReleaseManager::PerformUpgrade notices that the new release has been upgraded. It moves its state to upgraded which causes the NE to go to primary.


Scenario Newgrade Between 3.1.0.cn2222 - 3.1.0.cn3333

The scenario starts where the ReleaseManager has transitioned to upgrade. <P>

Release 3.1.0.cn2222 is the old release and exists on disk. 3.1.0.cn3333 is the new release and it also exists on disk because it was installed. <P>

  1. The ReleaseManager sees a change number is involved. It checks to see if there is a SoftwareRelease for that particular change number. If not the change number is stripped and the SoftwareRelease is checked for again. The same process for 3.1.0.cn3333. If the two SoftwareRelease objects are the same then a samegrade happening. <P> The old SoftwareRelease is told to use 3.1.0.cn2222 for internal path naming purposes. A temporary SoftwareRelease object is cloned from the SoftwareRelease for 3.1.0.cn2222.
  2. SamegradePerform on release 3.1.0.cn3333 is called.
  3. SamegradePerform calls InstalledSamegradeDbSetup because 3.1.0.cn3333 is the new release.
  4. Loop through all the tables and perform the following algorithm:
    1. If a table in the new release has data then don't copy data from the old release.
    2. If a table in the new release does not have data and the old release has data then copy data from the old release to the new release.

    The upside of this approach is that it is automatic. <P>

    The downside of this approach is that we copy too much data and we miss updates in other data. We can work on a different approach if this isn't OK.

  5. InstalledNewgradeDbTeardown is called to rename 3.1.0.cn3333data back to data using DbManager::MakeTemporaryDataTheActualData.
  6. ReleaseManager::PerformUpgrade notices that the new release has been upgraded. ReleaseManager::UpgradeCompleted is called.


Scenario Downgrade Between 3.0.0 - 2.0.3

The scenario has two major parts:

  1. In the context of the old release. Most of the upgrade process for a downgrade happened in the old release.
  2. In the context of the new release.

New Release

Starts where the ReleaseManager has transitioned to upgrade. There's nothing to do as the dowgrade logic happened in the old release. The NewRelease knows a downgrade happened because the old release is not in its tables. <P>

UpgradeCompleted is called so the card will go to primary. <P>

Old Release

Downgrade occurs in the context of the old release, when it is the current release. <P>

Release 3.0.0 is the old release and exists on disk. 2.0.3 is the new release and it also exists on disk because it was either freshly installed or has a previous installation. The previous installation may have data. <P>

  1. Ask the ReleaseManager for 3.0.0. The 2.0.3 release is found by asking the ReleaseManager for the previous release before 2.0.3.
  2. DowngradePerform on release 2.0.3 is called. It can fail if 2.0.3 has no downgrade TableUpgrade entries. ReleaseManager::IsCanUpgrade should have already been called to determine if the upgrade could happen.
  3. DowngradePerform calls InstalledDowngradeDbSetup because 2.0.3 is the new release.
  4. InstalledDowngradeDbSetup renames the data directory in the release to C:\temp\2.0.3data. The old database is the real database in 3.0.0. The temporary directory is created using DbManager::MoveToTemporaryArea.
  5. Then the downgrade TableUpgrade list is executed.
  6. Schema is AcceptNew.
  7. ManagementObject is dropped.
  8. AAA and BBB are ReplaceWithOld so the existing records are deleted then all the records are copied over.
  9. CCC has a TableTransform so it can recreate the old CCC, CCC1, and CCC2 records. It must delete all the new CCC records.
  10. InstalledDowngradeDbTeardown is called to rename 2.0.3data back to data using DbManager::MakeTemporaryDataTheActualData.
  11. ReleaseManager::PerformUpgrade notices that the new release has been upgraded. ReleaseManager::UpgradeCompleted is called.


Scenarios for Restored Backup

TBD

Personal tools