server.cpp

来自「这是广泛使用的通信开源项目,对于大容量,高并发的通讯要求完全能够胜任,他广泛可用」· C++ 代码 · 共 788 行 · 第 1/2 页

CPP
788
字号
    AssetMap::iterator i;
    for (i = m_assets.begin (); i != m_assets.end (); i++) {
        afile << i->first << endl;
        if (!afile) {
            cerr << "Cannot update " << m_asset_file.in () << endl;
            assert (0);
        }
        delete i->second;
    }
    //afile.close ();
    //if (!afile) {
    //    cerr << "Cannot close " << m_asset_file << endl;
    //    assert (0);
    //}
}

CCS::Thermometer_ptr
Controller_impl::
create_thermometer (CCS::AssetType anum, const char * loc)
throw (CORBA::SystemException, CCS::Controller::DuplicateAsset)
{
    if (anum % 2 == 0)
        throw CORBA::BAD_PARAM ();   // Thermometers have odd numbers
    if (exists (anum))
        throw CCS::Controller::DuplicateAsset ();

    assert (ICP_online (anum) == 0);
    assert (ICP_set (anum, "location", loc) == 0);
    add_impl (anum, 0);
    return make_dref (m_poa.in (), anum);
}

CCS::Thermostat_ptr
Controller_impl::
create_thermostat (
    CCS::AssetType      anum,
    const char*     loc,
    CCS::TempType       temp)
throw (
    CORBA::SystemException,
    CCS::Controller::DuplicateAsset,
    CCS::Thermostat::BadTemp)
{
    if (anum % 2 != 0)
        throw CORBA::BAD_PARAM ();   // Thermostats have even numbers
    if (exists (anum))
        throw CCS::Controller::DuplicateAsset ();

    assert (ICP_online (anum) == 0);
    assert (ICP_set (anum, "location", loc) == 0);
    // Set the nominal temperature.
    if (ICP_set (anum, "nominal_temp", &temp) != 0) {

        // If ICP_set () failed, read this thermostat's minimum
        // and maximum so we can initialize the BadTemp exception.
        CCS::Thermostat::BtData btd;
        ICP_get (
            anum, "MIN_TEMP",
            &btd.min_permitted, sizeof (btd.min_permitted)
        );
        ICP_get (
            anum, "MAX_TEMP",
            &btd.max_permitted, sizeof (btd.max_permitted)
        );
        btd.requested = temp;
        btd.error_msg = CORBA::string_dup (
            temp > btd.max_permitted ? "Too hot" : "Too cold"
        );
        ICP_offline (anum);
        throw CCS::Thermostat::BadTemp (btd);
    }

    add_impl (anum, 0);
    CORBA::Object_var obj = make_dref (m_poa.in (), anum);
    return CCS::Thermostat::_narrow (obj.in ());
}

// IDL list operation.

CCS::Controller::ThermometerSeq *
Controller_impl::
list () throw (CORBA::SystemException)
{
    // Create a new thermometer sequence. Because we know
    // the number of elements we will put onto the sequence,
    // we use the maximum constructor.
    CCS::Controller::ThermometerSeq_var listv
        = new CCS::Controller::ThermometerSeq (m_assets.size ());
    listv->length (m_assets.size ());

    // Loop over the m_assets set and create a
    // reference for each device.
    CORBA::ULong count = 0;
    AssetMap::iterator i;
    for (i = m_assets.begin (); i != m_assets.end (); i++)
        listv[count++] = make_dref (m_poa.in (), i->first);
    return listv._retn ();
}

// IDL change operation.

void
Controller_impl::
change (
    const CCS::Controller::ThermostatSeq &  tlist,
    CORBA::Short                            delta
) throw (CORBA::SystemException, CCS::Controller::EChange)
{
    CCS::Controller::EChange ec;    // Just in case we need it

    // We cannot add a delta value to a thermostat's temperature
    // directly, so for each thermostat, we read the nominal
    // temperature, add the delta value to it, and write
    // it back again.
    for (CORBA::ULong i = 0; i < tlist.length (); i++) {
        if (CORBA::is_nil (tlist[i]))
            continue;                       // Skip nil references

        // Read nominal temp and update it.
        CCS::TempType tnom = tlist[i]->get_nominal ();
        tnom += delta;
        try {
            tlist[i]->set_nominal (tnom);
        }
        catch (const CCS::Thermostat::BadTemp &bt) {
            // If the update failed because the temperature
            // is out of range, we add the thermostat's info
            // to the errors sequence.
            CORBA::ULong len = ec.errors.length ();
            ec.errors.length (len + 1);
            ec.errors[len].tmstat_ref = tlist[i].in ();
            ec.errors[len].info = bt.details;
        }
    }

    // If we encountered errors in the above loop,
    // we will have added elements to the errors sequence.
    if (ec.errors.length () != 0)
        throw ec;
}

// IDL find operation

void
Controller_impl::
find (CCS::Controller::SearchSeq & slist)
throw (CORBA::SystemException)
{
    // Loop over input list and lookup each device.
    CORBA::ULong listlen = slist.length ();
    for (CORBA::ULong i = 0; i < listlen; i++) {

        AssetMap::iterator where;   // Iterator for asset set
        int num_found = 0;          // Num matched per iteration

        // Assume we will not find a matching device.
        slist[i].device = CCS::Thermometer::_nil ();

        // Work out whether we are searching by asset,
        // model, or location.
        CCS::Controller::SearchCriterion sc = slist[i].key._d ();
        if (sc == CCS::Controller::ASSET) {
            // Search for matching asset number.
            where = m_assets.find (slist[i].key.asset_num ());
            if (where != m_assets.end ())
                slist[i].device = make_dref (m_poa.in (), where->first);
        } else {
            // Search for model or location string.
            const char *search_str;
            if (sc == CCS::Controller::LOCATION)
                search_str = slist[i].key.loc ();
            else
                search_str = slist[i].key.model_desc ();

            // Find first matching device (if any).
            where = find_if (
                        m_assets.begin (), m_assets.end (),
                        StrFinder (sc, search_str)
                    );

            // While there are matches...
            while (where != m_assets.end ()) {
                if (num_found == 0) {
                    // First match overwrites reference
                    // in search record.
                    slist[i].device = make_dref (m_poa.in (), where->first);
                } else {
                    // Further matches each append a new
                    // element to the search sequence.
                    CORBA::ULong len = slist.length ();
                    slist.length (len + 1);
                    slist[len].key = slist[i].key;
                    slist[len].device = make_dref (m_poa.in (), where->first);
                }
                num_found++;

                // Find next matching device with this key.
                where = find_if (
                            ++where, m_assets.end (),
                            StrFinder (sc, search_str)
                        );
            }
        }
    }
}

//----------------------------------------------------------------

DeviceLocator_impl::
DeviceLocator_impl (Controller_impl * ctrl) : m_ctrl (ctrl)
{
    // Intentionally empty
}

PortableServer::Servant
DeviceLocator_impl::
preinvoke (
    const PortableServer::ObjectId & oid,
    PortableServer::POA_ptr          /* poa */,
    const char *                     operation,
    void * &                         /* cookie */
) throw (CORBA::SystemException, PortableServer::ForwardRequest)
{
    // Convert object id into asset number.
    CORBA::String_var oid_string;
    try {
        oid_string = PortableServer::ObjectId_to_string (oid);
    } catch (const CORBA::BAD_PARAM &) {
        throw CORBA::OBJECT_NOT_EXIST ();
    }

    if (strcmp (oid_string.in (), Controller_oid) == 0)
        return m_ctrl;

    istrstream istr (oid_string.in ());
    CCS::AssetType anum;
    istr >> anum;
    if (istr.fail ())
        throw CORBA::OBJECT_NOT_EXIST ();

    // Check whether the device is known.
    if (!m_ctrl->exists (anum))
        throw CORBA::OBJECT_NOT_EXIST ();

    // Look at the object map to find out whether
    // we have a servant in memory.
    Thermometer_impl * servant;
    ActiveObjectMap::iterator servant_pos = m_aom.find (anum);
    if (servant_pos  == m_aom.end ()) {
        // No servant in memory. If evictor queue is full,
        // evict servant at head of queue.
        if (m_eq.size () == MAX_EQ_SIZE) {
            servant = m_eq.back ();
            m_aom.erase (servant->m_anum);
            m_eq.pop_back ();
            delete servant;
        }
        // Instantiate correct type of servant.
        char buf[32];
        assert (ICP_get (anum, "model", buf, sizeof (buf)) == 0);
        if (strcmp (buf, "Sens-A-Temp") == 0)
            servant = new Thermometer_impl (anum);
        else
            servant = new Thermostat_impl (anum);
    } else {
        // Servant already in memory.
        servant = * (servant_pos->second);   // Remember servant
        m_eq.erase (servant_pos->second);    // Remove from queue

        // If operation is "remove", also remove entry from
        // active object map -- the object is about to be deleted.
        if (strcmp (operation, "remove") == 0)
            m_aom.erase (servant_pos);
    }

    // We found a servant, or just instantiated it.
    // If the operation is not a remove, move
    // the servant to the tail of the evictor queue
    // and update its queue position in the map.
    if (strcmp (operation, "remove") != 0) {
        m_eq.push_front (servant);
        m_aom[anum] = m_eq.begin ();
    }

    return servant;
}

//----------------------------------------------------------------

int
main (int argc, char * argv[])
{
    CORBA::ORB_var orb;

    try {
        // Initialize orb
        orb = CORBA::ORB_init (argc, argv);

        // Get reference to Root POA.
        CORBA::Object_var obj
            = orb->resolve_initial_references ("RootPOA");
        PortableServer::POA_var poa
            = PortableServer::POA::_narrow (obj.in ());

        // Get POA manager
        PortableServer::POAManager_var poa_mgr = poa->the_POAManager ();

        // Create a policy list. We use persistent objects with
        // user-assigned IDs, and explicit activation.
        CORBA::PolicyList policy_list;
        policy_list.length (6);
        policy_list[0] = poa->create_lifespan_policy (
                            PortableServer::TRANSIENT   // REVISIT
                         );
        policy_list[1] = poa->create_id_assignment_policy (
                            PortableServer::USER_ID
                         );
        policy_list[2] = poa->create_implicit_activation_policy (
                            PortableServer::NO_IMPLICIT_ACTIVATION
                         );
        policy_list[3] = poa->create_request_processing_policy (
                            PortableServer::USE_SERVANT_MANAGER
                         );
        policy_list[4] = poa->create_servant_retention_policy (
                            PortableServer::NON_RETAIN
                         );
        policy_list[5] = poa->create_thread_policy (
                            PortableServer::SINGLE_THREAD_MODEL
                         );

        // Create a POA for all CCS elements.
        PortableServer::POA_var ccs_poa
            = poa->create_POA ("CCS_POA", poa_mgr.in (), policy_list);

        // Create a controller and set static m_ctrl member
        // for thermostats and thermometers.
        Controller_impl ctrl_servant (ccs_poa.in (), "/tmp/CCS_assets");
        Thermometer_impl::m_ctrl = &ctrl_servant;

        // Create a reference for the controller and
        // create the corresponding CORBA object.
        PortableServer::ObjectId_var oid
            = PortableServer::string_to_ObjectId (Controller_oid);
        CORBA::Object_var ctrl
            = ccs_poa->create_reference_with_id (
                oid.in (), "IDL:acme.com/CCS/Controller:1.0"
              );

        // Get reference to initial naming context.
        CosNaming::NamingContext_var inc
            = resolve_init<CosNaming::NamingContext> (
                    orb.in (), "NameService"
              );

        // Attempt to create CCS context.
        CosNaming::Name n;
        n.length (1);
        n[0].id = CORBA::string_dup ("CCS");
        try {
            CosNaming::NamingContext_var nc
                = inc->bind_new_context (n);
        } catch (const CosNaming::NamingContext::AlreadyBound &) {
            // Fine, CCS context already exists.
        }

        // Force binding of controller reference to make
        // sure it is always up-to-date.
        n.length (2);
        n[1].id = CORBA::string_dup ("Controller");
        inc->rebind (n, ctrl.in ());

        // Instantiate the servant locator for devices.
        PortableServer::ServantManager_var locator =
          new DeviceLocator_impl (&ctrl_servant);

        // Set servant locator.
        ccs_poa->set_servant_manager (locator.in ());

        // Activate the POA manager.
        poa_mgr->activate ();

        // Accept requests
        orb->run ();
    }
    catch (const CORBA::Exception & e) {
        cerr << "Uncaught CORBA exception: " << e << endl;
        return 1;
    }
    catch (...) {
        assert (0);  // Uncaught exception, dump core
    }
    return 0;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?