/*
 * SPDX-FileCopyrightText: 2004 Copyright contributors to the cppTango project
 *
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */

#include <tango/server/Util.h>

#include <tango/client/Database.h>
#include <tango/client/EventConsumer.h>
#include <tango/server/DServer.h>
#include <tango/server/DServerClass.h>
#include <tango/server/NotifdEventSupplier.h>
#include <tango/server/ZmqEventSupplier.h>

namespace Tango
{
//+----------------------------------------------------------------------------
//
// method :         Util::shutdown_ds()
//
// description :     This method sends command to the polling thread for
//            all cmd/attr with polling configuration stored in db.
//            This is done in separate thread in order to equally
//            spread all the polled objects polling time on the
//            smallest polling period.
//
//-----------------------------------------------------------------------------

void Util::shutdown_ds()
{
    //
    // Stopping a device server means :
    //        - Mark the server as shutting down
    //        - Send kill command to the polling thread
    //        - Join with this polling thread
    //        - Unregister server in database
    //        - Delete devices (except the admin one)
    //        - Stop the KeepAliveThread and the EventConsumer Thread when
    //          they have been started to receive events
    //        - Force writing file database in case of
    //        - Shutdown the ORB
    //

    set_svr_shutting_down(true);

    //
    // send the exit command to all the polling threads in the pool
    //

    stop_all_polling_threads();
    stop_heartbeat_thread();
    clr_heartbeat_th_ptr();

    //
    // Unregister the server in the database
    //

    try
    {
        unregister_server();
    }
    catch(...)
    {
    }

    //
    // Delete the devices (except the admin one)
    //

    get_dserver_device()->delete_devices();

    //
    //     Stop the KeepAliveThread and the EventConsumer thread when
    //  they have been started to receive events.
    //

    ApiUtil *au = ApiUtil::instance();
    au->shutdown_event_consumers();

    //
    // Disconnect the server from the notifd, when it was connected
    //

    NotifdEventSupplier::cleanup();

    //
    // Delete ZmqEventSupplier
    //

    ZmqEventSupplier::cleanup();

    //
    // Close access to file database when used
    //

    if(_FileDb)
    {
        Database *db_ptr = get_database();
        db_ptr->write_filedatabase();
        delete db_ptr;
        TANGO_LOG_DEBUG << "Database object deleted" << std::endl;
    }

    //
    // If the server uses its own event loop, do not call it any more
    //

    if(is_server_event_loop_set())
    {
        set_shutdown_server(true);
    }

    DServerClass::cleanup();

    //
    // Shutdown the ORB
    //

    TANGO_LOG_DEBUG << "Going to shutdown ORB" << std::endl;
    CORBA::ORB_var loc_orb = get_orb();
    loc_orb->shutdown(true);

    TANGO_LOG_DEBUG << "ORB shutdown" << std::endl;
}

} // namespace Tango
