javacommons/utils/functionserver/src/functionserver.cpp
branchRCL_3
changeset 19 04becd199f91
child 23 98ccebc37403
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javacommons/utils/functionserver/src/functionserver.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,358 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  ?Description
+*
+*/
+
+
+#include <sstream>
+#include "functionserver.h"
+#include "fs_methodcall.h"
+#include "logger.h"
+#include "monitor.h"
+
+using namespace java::util;
+
+/**
+ *
+ */
+OS_EXPORT FunctionServer::FunctionServer(const std::string& serverName) :
+        mJniEnv(0),mJavaPeerObject(0),mJavaPeerClass(0),
+        mServerName(serverName), mMonitor(0), mJavaVm(0), mConnectedToClient(false),
+        mOsServer(0), mServerTerminating(false), mServerRunningInSameThread(true),
+        mDeleteThisObj(false)
+{
+    JELOG2(EUtils);
+    int identifier = (int)this;
+    std::ostringstream uniqServerName;
+    uniqServerName <<serverName << "_" << identifier;
+    mServerName = uniqServerName.str();
+}
+
+/**
+ *
+ */
+OS_EXPORT FunctionServer::~FunctionServer()
+{
+    JELOG2(EUtils);
+    // delete mMonitor;
+    // mMonitor = 0;
+
+    // delete mOsServer;
+    // mOsServer = 0;
+
+}
+
+/**
+ *
+ */
+OS_EXPORT void FunctionServer::stopServer()
+{
+    JELOG2(EUtils);
+    ScopedLock lock(mMutex);
+
+    mServerTerminating = true;
+    if (!mConnectedToClient)
+    {
+        mClient.connect(*mOsServer);
+        mConnectedToClient = true;
+    }
+
+    mClient.sendCloseMessage(this);
+    mClient.Close();
+    mMonitor->wait();
+}
+
+
+int FunctionServer::doAttachToVm(JavaVM* javaVm, jobject peer)
+{
+    JELOG2(EUtils);
+    mJavaVm = javaVm;
+    mJavaPeerObject = peer;
+    int result = mJavaVm->AttachCurrentThread((void**)&mJniEnv, 0);
+    if (result == 0)
+    {
+        result = -1;
+        jclass clz = mJniEnv->GetObjectClass(mJavaPeerObject);
+        if (clz != 0)
+        {
+            result = 0;
+            mJavaPeerClass = static_cast<jclass>(mJniEnv->NewGlobalRef(clz));
+            // mJavaPeerClass = clz;
+            vmAttached();
+        }
+    }
+    LOG1(EUtils, EInfo, "FunctionServer::doAttachToVm(), status: %d", result);
+    return result;
+}
+
+OS_EXPORT void FunctionServer::vmAttached()
+{
+    JELOG2(EUtils);
+}
+
+OS_EXPORT void FunctionServer::vmDetached()
+{
+    JELOG2(EUtils);
+}
+/**
+ *
+ */
+OS_EXPORT void FunctionServer::attachToVm(JNIEnv& env, jobject peer)
+{
+    JELOG2(EUtils);
+    JavaVM* vm;
+    int status = 0;
+    env.GetJavaVM(&vm); // Get pointer to VM
+    if (vm)
+    {
+        jobject globalPeer = env.NewGlobalRef(peer);
+        if (globalPeer == 0)
+        {
+            ELOG(EJavaRuntime, "JNI attachUiToVm(), NewGlobalRef(() failed");
+            status = -1;
+        }
+        else
+        {
+            CallMethod(status, this, &FunctionServer::doAttachToVm, vm, globalPeer, this);
+
+            if (status != 0)
+            {
+                ELOG(EJavaRuntime, "JNI attachUiToVm(), attachToVm(() failed");
+                env.DeleteGlobalRef(globalPeer);
+            }
+        }
+    }
+}
+
+int FunctionServer::doDetachFromVm()
+{
+    JELOG2(EUtils);
+
+    int result = -1;
+
+    if (mJavaPeerObject)
+    {
+        // Causes crash currently
+        mJniEnv->DeleteGlobalRef(mJavaPeerObject);
+        mJavaPeerObject = 0;
+    }
+
+    if (mJavaPeerClass)
+    {
+        // Causes crash currently
+        mJniEnv->DeleteGlobalRef(mJavaPeerClass);
+        mJavaPeerClass = 0;
+    }
+
+    if (mJavaVm)
+    {
+        mJavaVm->DetachCurrentThread();
+        mJavaVm = 0;
+        vmDetached();
+        result = 0;
+    }
+    return result;
+}
+
+/**
+ *
+ */
+OS_EXPORT void FunctionServer::detachFromVm()
+{
+    JELOG2(EUtils);
+    int status = -1;
+    CallMethod(status, this, &FunctionServer::doDetachFromVm, this);
+    LOG1(EJavaUI, EInfo, "JavaUi::doDetachFromVm(), status: %d", status);
+}
+
+#define SERVER_STACKSIZE 0x2000
+
+
+/**
+ *
+ */
+OS_EXPORT void FunctionServer::createServerToNewThread()
+{
+    JELOG2(EUtils);
+
+    // This method initializes all datamembers. This is needed in re-starting
+    // server use case.
+    init();
+
+    // Start the VM into separate thread
+    pthread_t tid;
+    pthread_attr_t* threadArgs = 0;
+    mMonitor.reset(Monitor::createMonitor());
+    // mMonitor = Monitor::createMonitor();
+    int result = pthread_create(&tid, threadArgs, serverThreadEntryPoint, this);
+    mMonitor->wait();
+
+}
+
+/**
+ *
+ */
+void* FunctionServer::serverThreadEntryPoint(void* ptr)
+{
+    JELOG2(EUtils);
+    FunctionServer* server = reinterpret_cast<FunctionServer*>(ptr);
+    server->mServerRunningInSameThread = false;
+    server->mOsServer = new OsFunctionServer();
+    server->mOsServer->osThreadInit();
+    server->createAndStartSrv();
+    server->mOsServer->osThreadClean();
+    server->doServerSideClean();
+    delete server->mOsServer;
+    server->mOsServer = 0;
+    server->mMonitor->notify();
+    pthread_exit(0);
+    if (true == server->mDeleteThisObj)
+    {
+        delete server;
+    }
+    return 0;
+}
+
+/**
+ *
+ */
+OS_EXPORT void FunctionServer::createServerToCurrentThread()
+{
+    JELOG2(EUtils);
+
+    // This method initializes all datamembers. This is needed in re-starting
+    // server use case.
+    init();
+    createAndStartSrv();
+}
+
+/**
+ *
+ */
+OS_EXPORT void FunctionServer::createAndStartSrv()
+{
+    JELOG2(EUtils);
+
+    doServerSideInit();
+    if (mOsServer == 0)
+    {
+        mOsServer = new OsFunctionServer();
+    }
+    mOsServer->startOsServer();
+    if (mMonitor.get())
+    {
+        mMonitor->notify();
+    }
+    startServer();
+    if (mServerRunningInSameThread)
+    {
+        doServerSideClean();
+        delete mOsServer;
+        mOsServer = 0;
+        mMonitor->notify();
+    }
+}
+
+/**
+ *
+ */
+OS_EXPORT void FunctionServer::startServer()
+{
+    JELOG2(EUtils);
+    CActiveScheduler::Start();
+    delete CActiveScheduler::Current();         // will delete all objects
+}
+/**
+ *
+ */
+OS_EXPORT void FunctionServer::doServerSideInit()
+{
+    JELOG2(EUtils);
+    CActiveScheduler* scheduler = new CActiveScheduler;
+    CActiveScheduler::Install(scheduler);
+}
+
+/**
+ *
+ */
+OS_EXPORT void FunctionServer::doServerSideClean()
+{
+    JELOG2(EUtils);
+}
+
+
+/**
+ *
+ */
+OS_EXPORT void FunctionServer::stopServerInsideServerThread(bool aDeleteThisObj)
+{
+    JELOG2(EUtils);
+    // ScopedLock was comment out because deadlock occurs if this
+    // operation is called inside user's method passed as argument to CallMethodL() operation.
+    // There is a tiny risk that this causes problem when 'mServerTerminating' datamember
+    // is read in executeInServerThread() operation.
+    // ScopedLock lock(mMutex);
+    mServerTerminating = true;
+    mDeleteThisObj = aDeleteThisObj;
+
+    if (mOsServer)
+    {
+        mOsServer->stopServerInsideServerThread();
+    }
+}
+
+
+void FunctionServer::init()
+{
+    JELOG2(EUtils);
+    mMonitor.reset(0);
+    doDetachFromVm();
+    mConnectedToClient = false;
+    if (mOsServer)
+    {
+        delete mOsServer;
+        mOsServer = 0;
+    }
+    mServerTerminating = false;
+    mServerRunningInSameThread = true;
+    mDeleteThisObj = false;
+}
+
+int FunctionServer::executeInServerThread(const Functor& functor)
+{
+    JELOG2(EUtils);
+    // See stopServerInsideServerThread operation.
+    // ScopedLock lock(mMutex);
+    if (mServerTerminating)
+    {
+        std::string message = "Trying to execute code in non-existing FS: ";
+        message.append(mServerName);
+        ELOG1(EUtils,"%s", message.c_str());
+        throw ExceptionBase(message, __FILE__, __FUNCTION__, __LINE__);
+    }
+    if (!mConnectedToClient)
+    {
+        int err = mClient.connect(*mOsServer);
+        if (err != 0)
+        {
+            return err;
+        }
+        mConnectedToClient = true;
+    }
+    int res = mClient.execute(functor);
+    return res;
+}
+
+