Forum Stats

  • 3,854,655 Users
  • 2,264,394 Discussions
  • 7,905,747 Comments

Discussions

An example how to create a migratable session

1869412
1869412 Member Posts: 1
edited Oct 5, 2015 9:50AM in Oracle Call Interface (OCI)

Hello,

I am trying to create a migratable session. Having exhaustively reviewed what is available on the subject, this is the code I came up with, which doesn't work:

#include <oci.h>

#include <cstdlib>

#include <cstring>

#include <exception>

#include <stdexcept>

#include <vector>

#include <iostream>

void check(sword status, OCIError* errh)

{

    switch (status) {

    case OCI_SUCCESS:

        break;

    case OCI_INVALID_HANDLE:

        throw std::logic_error("invalid handle\n");

    case OCI_ERROR:

    {

        sb4                     code;

        std::vector<OraText>    buf(OCI_ERROR_MAXMSG_SIZE);

        std::string             txt;

        switch (const sword s = OCIErrorGet(errh, 1, 0, &code, &buf[0], buf.size() * sizeof (OraText), OCI_HTYPE_ERROR)) {

        case OCI_SUCCESS:

            if (!std::uncaught_exception())

                throw std::runtime_error(reinterpret_cast<const char*>(&buf[0]));

            std::clog << reinterpret_cast<const char*>(&buf[0]) << std::endl;

            break;

        default:

            std::clog << "OCIErrorGet: status " << s << std::endl;

        }

    }

    default:

        std::clog << "check: status " << status << std::endl;

    }

}

int main()

try {

    std::clog << "creating environment..." << std::endl;

    OCIEnv* envh;

    if (OCIEnvCreate(&envh, OCI_DEFAULT, 0, 0, 0, 0, 0, 0) == OCI_INVALID_HANDLE)

        throw std::runtime_error("failed to create environment\n");

    std::clog << "allocating OCIError..." << std::endl;

    OCIError* errh;

    if (OCIHandleAlloc(envh, (void**)&errh, OCI_HTYPE_ERROR, 0, 0) == OCI_INVALID_HANDLE)

        throw std::runtime_error("failed to allocate OCIError\n");

    std::clog << "allocating OCIServer..." << std::endl;

    OCIServer* srvh;

    if (OCIHandleAlloc(envh, (void**)&srvh, OCI_HTYPE_SERVER, 0, 0) == OCI_INVALID_HANDLE)

        throw std::runtime_error("failed to allocate server\n");

    std::clog << "attaching server..." << std::endl;

    check(OCIServerAttach(srvh, errh, (const OraText*)"server", std::strlen("server"), OCI_DEFAULT), errh);

    std::clog << "allocating OCISvcCtx..." << std::endl;

    OCISvcCtx* svch;

    if (OCIHandleAlloc(envh, (void**)&svch, OCI_HTYPE_SVCCTX, 0, 0) == OCI_INVALID_HANDLE)

        throw std::runtime_error("failed to allocate context\n");

    std::clog << "allocating OCISession..." << std::endl;

    OCISession* sesh;

    if (OCIHandleAlloc(envh, (void**)&sesh, OCI_HTYPE_SESSION, 0, 0) == OCI_INVALID_HANDLE)

        throw std::runtime_error("failed to allocate session\n");

    check(OCIAttrSet(sesh, OCI_HTYPE_SESSION, (void*)"user_name", std::strlen("user_name"), OCI_ATTR_USERNAME, errh), errh);

    check(OCIAttrSet(sesh, OCI_HTYPE_SESSION, (void*)"password", std::strlen("password"), OCI_ATTR_PASSWORD, errh), errh);

    check(OCIAttrSet(svch, OCI_HTYPE_SVCCTX, srvh, 0, OCI_ATTR_SERVER, errh), errh);

    std::clog << "starting session..." << std::endl;

    check(OCISessionBegin(svch, errh, sesh, OCI_CRED_RDBMS, OCI_DEFAULT), errh);

    check(OCIAttrSet(svch, OCI_HTYPE_SVCCTX, sesh, 0, OCI_ATTR_SESSION, errh), errh);

    std::clog << "session started" << std::endl;

    std::clog << "reading session ID..." << std::endl;

    ub1* ses_id;

    ub4 sz;

    check(OCIAttrGet(sesh, OCI_HTYPE_SESSION, &ses_id, &sz, OCI_ATTR_MIGSESSION, errh), errh);

    {

        std::clog << "allocating new OCISvcCtx..." << std::endl;

        OCISvcCtx* svch;

        if (OCIHandleAlloc(envh, (void**)&svch, OCI_HTYPE_SVCCTX, 0, 0) == OCI_INVALID_HANDLE)

            throw std::runtime_error("failed to allocate new context\n");

        std::clog << "allocating new OCISession..." << std::endl;

        OCISession* sesh;

        if (OCIHandleAlloc(envh, (void**)&sesh, OCI_HTYPE_SESSION, 0, 0) == OCI_INVALID_HANDLE)

            throw std::runtime_error("failed to allocate new session\n");

        check(OCIAttrSet(sesh, OCI_HTYPE_SESSION, ses_id, sz, OCI_ATTR_MIGSESSION, errh), errh);

        std::clog << "allocating new OCIServer..." << std::endl;

        OCIServer* srvh;

        if (OCIHandleAlloc(envh, (void**)&srvh, OCI_HTYPE_SERVER, 0, 0) == OCI_INVALID_HANDLE)

            throw std::runtime_error("failed to allocate new server\n");

        std::clog << "attaching new server..." << std::endl;

        check(OCIServerAttach(srvh, errh, (const OraText*)"server", std::strlen("server"), OCI_DEFAULT), errh);

        check(OCIAttrSet(svch, OCI_HTYPE_SVCCTX, srvh, 0, OCI_ATTR_SERVER, errh), errh);

        std::clog << "starting new session..." << std::endl;

        check(OCISessionBegin(svch, errh, sesh, OCI_CRED_EXT, OCI_MIGRATE), errh);

        std::clog << "new session started" << std::endl;

    }

}

catch (const std::exception& e) {

    std::clog << e.what() << std::flush;

}

This is output:

creating environment...

allocating OCIError...

allocating OCIServer...

attaching server...

allocating OCISvcCtx...

allocating OCISession...

starting session...

session started

reading session ID...

allocating new OCISvcCtx...

allocating new OCISession...

allocating new OCIServer...

attaching new server...

starting new session...

ORA-24313: user already authenticated

Any example of code that would work?

Thank you.

Kind regards,

Paul

This discussion has been closed.