OTA Updater C++

Namespaces

 dpyOtaupdater
 Deepsy Otaupdater namespace that includes the different enums, structs or method signatures that should be used.
 

Classes

class  OtaUpdater
 Allows to interact with a ota updater service. More...
 

Detailed Description

OTA Updater API related documentation

Calling to OtaUpdater::asyncGetStatus will provide us information about the current state of the OTA Updater system and the alternative RFS. When the system is with no activity the system is in state IDLE. However the alternative RFS can be in these states:

Status BACKUP

This state means that the alternative RFS has a previous version of the RFS. We can check the differences with OtaUpdater::asyncGetVersions. In this state we have three possibilities:

  • Do an operation (OtaUpdater::asyncInstall , OtaUpdater::asyncUninstall , OtaUpdater::asyncUpdate): Next state will be IN_PROCESS
  • Discard changes (OtaUpdater::asyncDiscard): We will override backup RFS and the next state will be OK
  • Rollback to alternative RFS (OtaUpdater::asyncRollback): The next state will be UPGRADED

Status OK

This state means that the alternative RFS has the same information that the current RFS. In this state whe are only able to do an operation (OtaUpdater::asyncInstall , OtaUpdater::asyncUninstall , OtaUpdater::asyncUpdate). After the execution of one of these commands, the status will be IN_PROCESS.

Status IN_PROCESS

This state means that the alternative RFS has some changes regarding to current RFS. We can check the differences with OtaUpdater::asyncGetVersions. In this state we can

  • Continue doing operations (OtaUpdater::asyncInstall , OtaUpdater::asyncUninstall , OtaUpdater::asyncUpdate)
  • Discard changes (OtaUpdater::asyncDiscard): We will override backup RFS and the next state will be OK
  • Acknowledge the changes (OtaUpdater::asyncAck): The next state will be UPGRADED

Status UPGRADED

When the alternative RFS is in state UPGRADED we will not be able to do any operation after next reboot. This state means that the alternative RFS is ready for being used as current RFS in next boot.

Status ERROR

This state means that the alternative RFS is inconsistent. This happens when the system is restoring alternative RFS with current RFS data. This could happen:

  • When system is in BACKUP and we do an operation (OtaUpdater::asyncInstall , OtaUpdater::asyncUninstall , OtaUpdater::asyncUpdate).
  • When system is in BACKUP and we discard changes (OtaUpdater::asyncDiscard).
  • When system is in IN_PROCESS and we discard changes (OtaUpdater::asyncDiscard).
  • When system is in ERROR: This happens with a failed update (see Concepts/Update page).

During this "recoveries" the alternative RFS will have inconsistent data for a while, being indicated by state ERROR.

Managing versions

Synchronize

We can check if there are updates calling to OtaUpdater::asyncRepoSync. When performing a synchronize operation the system will be in SYNCHRONIZING status, returning back to IDLE when it finishes.

Get updates

After doing a synchronization, we can call to OtaUpdater::asyncGetUpdates in order to get the list of updates of the server.

Get versions

We can call OtaUpdater::asyncGetVersions to check the different versions between current RFS and alternative RFS. This will provide us information about the operations performed (packages installed, removed or upgraded).

Get remote versions

We can call OtaUpdater::asyncGetRemoteVersions to check the packages versions available in the remote repository.

Examples

  • Creating a class object

    #include <dpy/otaupdaterApi.h>
    OtaUpdater updater;


  • Asking for status

    #include <dpy/otaupdaterApi.h>
    #include <iostream>
    #include <boost/thread.hpp>
    volatile bool waiting = true;
    void status_handler(boost::system::error_code error_code, int status, int rfsstatus)
    {
    if (error_code) {
    std::cout << "\rError : " << error_code.message() << std::endl;
    } else {
    std::string s_status, rfs_status;
    switch (status) {
    s_status = "INITIALIZING";
    break;
    s_status = "SYNCHRONIZING";
    break;
    s_status = "IDLE";
    break;
    s_status = "RECOVERING";
    break;
    s_status = "OPERATING";
    break;
    s_status = "END";
    break;
    default:
    s_status = "UNKNOWN";
    break;
    }
    switch (rfsstatus) {
    rfs_status = "OK";
    break;
    rfs_status = "ERROR";
    break;
    rfs_status = "IN_PROCESS";
    break;
    rfs_status = "UPGRADED";
    break;
    rfs_status = "BACKUP";
    break;
    default:
    s_status = "UNKNOWN";
    break;
    }
    std::cout << "STATUS: System = "<< s_status << " | Alternative RFS = " << rfs_status << std::endl;
    }
    waiting = false;
    }
    int main()
    {
    OtaUpdater updater;
    updater.asyncGetStatus(status_handler);
    while (waiting) { //Waiting for handler to be called
    boost::this_thread::sleep_for(boost::chrono::seconds(1));
    }
    return 0;
    }

  • Executing a rollback

    #include <dpy/otaupdaterApi.h>
    #include <iostream>
    #include <boost/thread.hpp>
    volatile bool waiting = true;
    void result_handler(boost::system::error_code error_code)
    {
    if (error_code) {
    std::cout << "\rError : " << error_code.message() << std::endl;
    } else {
    std::cout << "\rAsynchronous operation forwarded successfully" << std::endl;
    }
    waiting = false;
    }
    int main()
    {
    OtaUpdater updater;
    updater.asyncRollback(result_handler);
    while (waiting) { //Waiting for handler to be called
    boost::this_thread::sleep_for(boost::chrono::seconds(1));
    }
    return 0;
    }

  • Getting all different versions

    #include <dpy/otaupdaterApi.h>
    #include <iostream>
    #include <boost/thread.hpp>
    volatile bool waiting = true;
    void versionsd_handler(boost::system::error_code error_code, std::map<std::string, std::pair<std::string, std::string>> &versionsMap)
    {
    if (error_code) {
    std::cout << "\rError : " << error_code.message() << std::endl;
    } else {
    bool headerPrinted = false;
    for (std::map<std::string, std::pair<std::string, std::string>>::iterator it = versionsMap.begin(); it != versionsMap.end(); ++it) {
    if (strcmp(it->second.first.c_str(), it->second.second.c_str()) != 0) {
    if (headerPrinted == false) {
    printf("%-40s \t %-30s \t %-30s\n", "package", "current RFS", "alternative RFS");
    printf("---------------------------------------- \t ------------------------------ \t ------------------------------\n");
    headerPrinted = true;
    }
    printf("%-40s \t %-30s \t %-30s\n", it->first.c_str(), it->second.first.c_str(), it->second.second.c_str());
    }
    }
    if (headerPrinted == false) {
    printf("There are no different versions for selected packages\n");
    }
    }
    fflush (stdout);
    waiting = false;
    }
    int main()
    {
    OtaUpdater updater;
    std::vector <std::string> packages;
    updater.asyncGetVersions(versionsd_handler, packages);
    while (waiting) { //Waiting for handler to be called
    boost::this_thread::sleep_for(boost::chrono::seconds(1));
    }
    return 0;
    }

  • Getting versions for specific packages

    #include <dpy/otaupdaterApi.h>
    #include <iostream>
    #include <boost/thread.hpp>
    volatile bool waiting = true;
    void versions_handler(boost::system::error_code error_code, std::map<std::string, std::pair<std::string, std::string>> &versionsMap)
    {
    if (error_code) {
    std::cout << "\rError : " << error_code.message() << std::endl;
    } else if (versionsMap.size() > 0) {
    printf("%-40s \t %-30s \t %-30s\n", "package", "current RFS", "alternative RFS");
    printf("---------------------------------------- \t ------------------------------ \t ------------------------------\n");
    for (std::map<std::string, std::pair<std::string, std::string>>::iterator it = versionsMap.begin(); it != versionsMap.end(); ++it) {
    printf("%-40s \t %-30s \t %-30s %s\n", it->first.c_str(), it->second.first.c_str(), it->second.second.c_str(),
    strcmp(it->second.first.c_str(), it->second.second.c_str()) != 0 ? "<---" : "");
    }
    } else {
    printf("There are no versions for selected packages\n");
    }
    fflush (stdout);
    waiting = false;
    }
    int main()
    {
    OtaUpdater updater;
    std::vector <std::string> packages;
    //If exact package name is unknown, by using the asterisk we would retrieve all packages starting with the specified name
    packages.push_back("deepsy*");
    packages.push_back("boost*");
    updater.asyncGetVersions(versions_handler, packages);
    while (waiting) { //Waiting for handler to be called
    boost::this_thread::sleep_for(boost::chrono::seconds(1));
    }
    return 0;
    }

  • Getting process percentage

    #include <dpy/otaupdaterApi.h>
    #include <iostream>
    #include <boost/thread.hpp>
    void result_handler(boost::system::error_code error_code)
    {
    if (error_code) {
    std::cout << "\rError : " << error_code.message() << std::endl;
    } else {
    std::cout << "\rAsynchronous operation forwarded successfully" << std::endl;
    }
    }
    void print_operation_percentage(boost::system::error_code ec, int operation, int percentage)
    {
    if (ec) {
    std::cout << "\rError : " << ec.message() << std::endl;
    } else {
    std::string s_operation;
    switch (operation) {
    s_operation = "NO_OPERATING";
    break;
    s_operation = "INSTALLING";
    break;
    s_operation = "UPGRADING";
    break;
    s_operation = "REMOVING";
    break;
    s_operation = "DOWNLOADING";
    break;
    default:
    s_operation = "UNKNOWN";
    break;
    }
    printf("\rPROCESS: %s - %d %%\n", s_operation.c_str(), percentage);
    fflush (stdout);
    }
    }
    void operation_percentage_handler(boost::system::error_code error_code, int operation, int percentage)
    {
    print_operation_percentage(error_code, operation, percentage);
    }
    int main()
    {
    OtaUpdater updater;
    std::vector<std::string> packages = { "deepsy-21" };
    updater.getOperationPercentage_S(operation_percentage_handler);
    updater.asyncInstall(result_handler);
    boost::this_thread::sleep_for(boost::chrono::seconds(5));
    return 0;
    }