javacommons/utils/functionserver/src/functionserver.cpp
branchRCL_3
changeset 19 04becd199f91
child 23 98ccebc37403
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  ?Description
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <sstream>
       
    20 #include "functionserver.h"
       
    21 #include "fs_methodcall.h"
       
    22 #include "logger.h"
       
    23 #include "monitor.h"
       
    24 
       
    25 using namespace java::util;
       
    26 
       
    27 /**
       
    28  *
       
    29  */
       
    30 OS_EXPORT FunctionServer::FunctionServer(const std::string& serverName) :
       
    31         mJniEnv(0),mJavaPeerObject(0),mJavaPeerClass(0),
       
    32         mServerName(serverName), mMonitor(0), mJavaVm(0), mConnectedToClient(false),
       
    33         mOsServer(0), mServerTerminating(false), mServerRunningInSameThread(true),
       
    34         mDeleteThisObj(false)
       
    35 {
       
    36     JELOG2(EUtils);
       
    37     int identifier = (int)this;
       
    38     std::ostringstream uniqServerName;
       
    39     uniqServerName <<serverName << "_" << identifier;
       
    40     mServerName = uniqServerName.str();
       
    41 }
       
    42 
       
    43 /**
       
    44  *
       
    45  */
       
    46 OS_EXPORT FunctionServer::~FunctionServer()
       
    47 {
       
    48     JELOG2(EUtils);
       
    49     // delete mMonitor;
       
    50     // mMonitor = 0;
       
    51 
       
    52     // delete mOsServer;
       
    53     // mOsServer = 0;
       
    54 
       
    55 }
       
    56 
       
    57 /**
       
    58  *
       
    59  */
       
    60 OS_EXPORT void FunctionServer::stopServer()
       
    61 {
       
    62     JELOG2(EUtils);
       
    63     ScopedLock lock(mMutex);
       
    64 
       
    65     mServerTerminating = true;
       
    66     if (!mConnectedToClient)
       
    67     {
       
    68         mClient.connect(*mOsServer);
       
    69         mConnectedToClient = true;
       
    70     }
       
    71 
       
    72     mClient.sendCloseMessage(this);
       
    73     mClient.Close();
       
    74     mMonitor->wait();
       
    75 }
       
    76 
       
    77 
       
    78 int FunctionServer::doAttachToVm(JavaVM* javaVm, jobject peer)
       
    79 {
       
    80     JELOG2(EUtils);
       
    81     mJavaVm = javaVm;
       
    82     mJavaPeerObject = peer;
       
    83     int result = mJavaVm->AttachCurrentThread((void**)&mJniEnv, 0);
       
    84     if (result == 0)
       
    85     {
       
    86         result = -1;
       
    87         jclass clz = mJniEnv->GetObjectClass(mJavaPeerObject);
       
    88         if (clz != 0)
       
    89         {
       
    90             result = 0;
       
    91             mJavaPeerClass = static_cast<jclass>(mJniEnv->NewGlobalRef(clz));
       
    92             // mJavaPeerClass = clz;
       
    93             vmAttached();
       
    94         }
       
    95     }
       
    96     LOG1(EUtils, EInfo, "FunctionServer::doAttachToVm(), status: %d", result);
       
    97     return result;
       
    98 }
       
    99 
       
   100 OS_EXPORT void FunctionServer::vmAttached()
       
   101 {
       
   102     JELOG2(EUtils);
       
   103 }
       
   104 
       
   105 OS_EXPORT void FunctionServer::vmDetached()
       
   106 {
       
   107     JELOG2(EUtils);
       
   108 }
       
   109 /**
       
   110  *
       
   111  */
       
   112 OS_EXPORT void FunctionServer::attachToVm(JNIEnv& env, jobject peer)
       
   113 {
       
   114     JELOG2(EUtils);
       
   115     JavaVM* vm;
       
   116     int status = 0;
       
   117     env.GetJavaVM(&vm); // Get pointer to VM
       
   118     if (vm)
       
   119     {
       
   120         jobject globalPeer = env.NewGlobalRef(peer);
       
   121         if (globalPeer == 0)
       
   122         {
       
   123             ELOG(EJavaRuntime, "JNI attachUiToVm(), NewGlobalRef(() failed");
       
   124             status = -1;
       
   125         }
       
   126         else
       
   127         {
       
   128             CallMethod(status, this, &FunctionServer::doAttachToVm, vm, globalPeer, this);
       
   129 
       
   130             if (status != 0)
       
   131             {
       
   132                 ELOG(EJavaRuntime, "JNI attachUiToVm(), attachToVm(() failed");
       
   133                 env.DeleteGlobalRef(globalPeer);
       
   134             }
       
   135         }
       
   136     }
       
   137 }
       
   138 
       
   139 int FunctionServer::doDetachFromVm()
       
   140 {
       
   141     JELOG2(EUtils);
       
   142 
       
   143     int result = -1;
       
   144 
       
   145     if (mJavaPeerObject)
       
   146     {
       
   147         // Causes crash currently
       
   148         mJniEnv->DeleteGlobalRef(mJavaPeerObject);
       
   149         mJavaPeerObject = 0;
       
   150     }
       
   151 
       
   152     if (mJavaPeerClass)
       
   153     {
       
   154         // Causes crash currently
       
   155         mJniEnv->DeleteGlobalRef(mJavaPeerClass);
       
   156         mJavaPeerClass = 0;
       
   157     }
       
   158 
       
   159     if (mJavaVm)
       
   160     {
       
   161         mJavaVm->DetachCurrentThread();
       
   162         mJavaVm = 0;
       
   163         vmDetached();
       
   164         result = 0;
       
   165     }
       
   166     return result;
       
   167 }
       
   168 
       
   169 /**
       
   170  *
       
   171  */
       
   172 OS_EXPORT void FunctionServer::detachFromVm()
       
   173 {
       
   174     JELOG2(EUtils);
       
   175     int status = -1;
       
   176     CallMethod(status, this, &FunctionServer::doDetachFromVm, this);
       
   177     LOG1(EJavaUI, EInfo, "JavaUi::doDetachFromVm(), status: %d", status);
       
   178 }
       
   179 
       
   180 #define SERVER_STACKSIZE 0x2000
       
   181 
       
   182 
       
   183 /**
       
   184  *
       
   185  */
       
   186 OS_EXPORT void FunctionServer::createServerToNewThread()
       
   187 {
       
   188     JELOG2(EUtils);
       
   189 
       
   190     // This method initializes all datamembers. This is needed in re-starting
       
   191     // server use case.
       
   192     init();
       
   193 
       
   194     // Start the VM into separate thread
       
   195     pthread_t tid;
       
   196     pthread_attr_t* threadArgs = 0;
       
   197     mMonitor.reset(Monitor::createMonitor());
       
   198     // mMonitor = Monitor::createMonitor();
       
   199     int result = pthread_create(&tid, threadArgs, serverThreadEntryPoint, this);
       
   200     mMonitor->wait();
       
   201 
       
   202 }
       
   203 
       
   204 /**
       
   205  *
       
   206  */
       
   207 void* FunctionServer::serverThreadEntryPoint(void* ptr)
       
   208 {
       
   209     JELOG2(EUtils);
       
   210     FunctionServer* server = reinterpret_cast<FunctionServer*>(ptr);
       
   211     server->mServerRunningInSameThread = false;
       
   212     server->mOsServer = new OsFunctionServer();
       
   213     server->mOsServer->osThreadInit();
       
   214     server->createAndStartSrv();
       
   215     server->mOsServer->osThreadClean();
       
   216     server->doServerSideClean();
       
   217     delete server->mOsServer;
       
   218     server->mOsServer = 0;
       
   219     server->mMonitor->notify();
       
   220     pthread_exit(0);
       
   221     if (true == server->mDeleteThisObj)
       
   222     {
       
   223         delete server;
       
   224     }
       
   225     return 0;
       
   226 }
       
   227 
       
   228 /**
       
   229  *
       
   230  */
       
   231 OS_EXPORT void FunctionServer::createServerToCurrentThread()
       
   232 {
       
   233     JELOG2(EUtils);
       
   234 
       
   235     // This method initializes all datamembers. This is needed in re-starting
       
   236     // server use case.
       
   237     init();
       
   238     createAndStartSrv();
       
   239 }
       
   240 
       
   241 /**
       
   242  *
       
   243  */
       
   244 OS_EXPORT void FunctionServer::createAndStartSrv()
       
   245 {
       
   246     JELOG2(EUtils);
       
   247 
       
   248     doServerSideInit();
       
   249     if (mOsServer == 0)
       
   250     {
       
   251         mOsServer = new OsFunctionServer();
       
   252     }
       
   253     mOsServer->startOsServer();
       
   254     if (mMonitor.get())
       
   255     {
       
   256         mMonitor->notify();
       
   257     }
       
   258     startServer();
       
   259     if (mServerRunningInSameThread)
       
   260     {
       
   261         doServerSideClean();
       
   262         delete mOsServer;
       
   263         mOsServer = 0;
       
   264         mMonitor->notify();
       
   265     }
       
   266 }
       
   267 
       
   268 /**
       
   269  *
       
   270  */
       
   271 OS_EXPORT void FunctionServer::startServer()
       
   272 {
       
   273     JELOG2(EUtils);
       
   274     CActiveScheduler::Start();
       
   275     delete CActiveScheduler::Current();         // will delete all objects
       
   276 }
       
   277 /**
       
   278  *
       
   279  */
       
   280 OS_EXPORT void FunctionServer::doServerSideInit()
       
   281 {
       
   282     JELOG2(EUtils);
       
   283     CActiveScheduler* scheduler = new CActiveScheduler;
       
   284     CActiveScheduler::Install(scheduler);
       
   285 }
       
   286 
       
   287 /**
       
   288  *
       
   289  */
       
   290 OS_EXPORT void FunctionServer::doServerSideClean()
       
   291 {
       
   292     JELOG2(EUtils);
       
   293 }
       
   294 
       
   295 
       
   296 /**
       
   297  *
       
   298  */
       
   299 OS_EXPORT void FunctionServer::stopServerInsideServerThread(bool aDeleteThisObj)
       
   300 {
       
   301     JELOG2(EUtils);
       
   302     // ScopedLock was comment out because deadlock occurs if this
       
   303     // operation is called inside user's method passed as argument to CallMethodL() operation.
       
   304     // There is a tiny risk that this causes problem when 'mServerTerminating' datamember
       
   305     // is read in executeInServerThread() operation.
       
   306     // ScopedLock lock(mMutex);
       
   307     mServerTerminating = true;
       
   308     mDeleteThisObj = aDeleteThisObj;
       
   309 
       
   310     if (mOsServer)
       
   311     {
       
   312         mOsServer->stopServerInsideServerThread();
       
   313     }
       
   314 }
       
   315 
       
   316 
       
   317 void FunctionServer::init()
       
   318 {
       
   319     JELOG2(EUtils);
       
   320     mMonitor.reset(0);
       
   321     doDetachFromVm();
       
   322     mConnectedToClient = false;
       
   323     if (mOsServer)
       
   324     {
       
   325         delete mOsServer;
       
   326         mOsServer = 0;
       
   327     }
       
   328     mServerTerminating = false;
       
   329     mServerRunningInSameThread = true;
       
   330     mDeleteThisObj = false;
       
   331 }
       
   332 
       
   333 int FunctionServer::executeInServerThread(const Functor& functor)
       
   334 {
       
   335     JELOG2(EUtils);
       
   336     // See stopServerInsideServerThread operation.
       
   337     // ScopedLock lock(mMutex);
       
   338     if (mServerTerminating)
       
   339     {
       
   340         std::string message = "Trying to execute code in non-existing FS: ";
       
   341         message.append(mServerName);
       
   342         ELOG1(EUtils,"%s", message.c_str());
       
   343         throw ExceptionBase(message, __FILE__, __FUNCTION__, __LINE__);
       
   344     }
       
   345     if (!mConnectedToClient)
       
   346     {
       
   347         int err = mClient.connect(*mOsServer);
       
   348         if (err != 0)
       
   349         {
       
   350             return err;
       
   351         }
       
   352         mConnectedToClient = true;
       
   353     }
       
   354     int res = mClient.execute(functor);
       
   355     return res;
       
   356 }
       
   357 
       
   358