Update ooo320-m1
[ooovba.git] / bridges / source / remote / urp / urp_environment.cxx
blob69a022302860ccf683107fa3a2f93e83afed2f95
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: urp_environment.cxx,v $
10 * $Revision: 1.21.20.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_bridges.hxx"
34 #include <stdio.h>
36 #include <osl/interlck.h>
37 #include <osl/diagnose.h>
38 #include <osl/conditn.h>
39 #include <osl/mutex.hxx>
40 #include <osl/process.h>
42 #include <rtl/alloc.h>
43 #include <rtl/uuid.h>
44 #include <rtl/unload.h>
46 #include <uno/environment.h>
47 #include <uno/lbnames.h>
48 #include <uno/mapping.hxx>
49 #include <uno/threadpool.h>
51 #include <com/sun/star/uno/Sequence.hxx>
53 #include <bridges/remote/proxy.hxx>
54 #include <bridges/remote/stub.hxx>
55 #include <bridges/remote/context.h>
56 #include <bridges/remote/mapping.hxx>
57 #include <bridges/remote/counter.hxx>
58 #include <bridges/remote/bridgeimpl.hxx>
59 #include <bridges/remote/helper.hxx>
61 #include "urp_bridgeimpl.hxx"
62 #include "urp_writer.hxx"
63 #include "urp_reader.hxx"
64 #include "urp_dispatch.hxx"
65 #include "urp_log.hxx"
66 #include "urp_propertyobject.hxx"
68 using namespace ::rtl;
69 using namespace ::osl;
70 using namespace ::com::sun::star::uno;
72 namespace bridges_urp
74 rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
76 // static void dumpProperties( struct Properties *p )
77 // {
78 // fprintf( stderr , "FlushBlockSize : %d\n" , p->nFlushBlockSize );
79 // fprintf( stderr , "OnewayTimeoutMUSEC : %d\n" , p->nOnewayTimeoutMUSEC );
80 // fprintf( stderr , "OidCacheSize : %d\n" , p->nOidCacheSize );
81 // fprintf( stderr , "TypeCacheSize : %d\n" , p->nTypeCacheSize );
82 // fprintf( stderr , "TidCacheSize : %d\n" , p->nTidCacheSize );
83 // OString o = OUStringToOString( p->sSupportedVersions , RTL_TEXTENCODING_ASCII_US );
84 // fprintf( stderr , "SupportedVersions : %s\n" , o.pData->buffer );
85 // o = OUStringToOString( p->sVersion , RTL_TEXTENCODING_ASCII_US );
86 // fprintf( stderr , "Version : %s\n" , o.pData->buffer );
87 // fprintf( stderr , "SupportsMultipleSynchronous : %d\n" , p->bSupportsMultipleSynchronous );
88 // fprintf( stderr , "SupportsMustReply : %d\n" , p->bSupportsMustReply );
89 // fprintf( stderr , "SupportsSynchronous : %d\n" , p->bSupportsSynchronous );
90 // }
92 // PropertySetterThread
93 //------------------------------------
94 class PropertySetterThread : public ::osl::Thread
96 urp_BridgeImpl *m_pImpl;
97 ::rtl::OUString m_sProps;
98 uno_Environment *m_pEnvRemote;
99 public:
100 PropertySetterThread( uno_Environment *pEnvRemote,
101 urp_BridgeImpl *pImpl,
102 const ::rtl::OUString & props )
103 : m_pImpl( pImpl )
104 , m_sProps( props )
105 , m_pEnvRemote( pEnvRemote )
107 if (m_sProps.getLength() > 0) {
108 m_sProps += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","));
110 m_sProps += rtl::OUString(
111 RTL_CONSTASCII_USTRINGPARAM("CurrentContext="));
112 // hold the environment in case all references are released before this
113 // thread terminates
114 m_pEnvRemote->acquire( pEnvRemote );
116 ~PropertySetterThread()
118 m_pEnvRemote->release( m_pEnvRemote );
121 virtual void SAL_CALL run()
123 for (;;)
125 switch ( m_pImpl->m_pPropertyObject->localRequestChange( ) )
127 case 1:
128 sal_Bool bExceptionThrown;
129 m_pImpl->m_pPropertyObject->localCommitChange( m_sProps , &bExceptionThrown );
130 OSL_ENSURE( !bExceptionThrown, "properties were not set\n" );
131 goto done;
132 case 0:
133 OSL_TRACE( "urp-bridge : remote-counterpart won the changing-the-protocol-race\n" );
134 goto done;
137 done:
138 m_pImpl->m_initialized.set();
140 virtual void SAL_CALL onTerminated()
142 delete this;
145 //------------------------------------
148 void test_cache()
150 OUString a = OUString( RTL_CONSTASCII_USTRINGPARAM( "a" ) );
151 OUString b = OUString( RTL_CONSTASCII_USTRINGPARAM( "b" ) );
152 OUString c = OUString( RTL_CONSTASCII_USTRINGPARAM( "c" ) );
153 Cache < OUString , equalOUString > cache ( 2 );
155 sal_Int32 n = cache.put( a );
156 if (cache.seek( a ) != n)
158 OSL_ASSERT( false );
160 OSL_ASSERT( 0 == n );
162 n = cache.put( b );
163 OSL_ASSERT( 1 == n );
165 cache.put( c );
167 OSL_ASSERT( 0xffff == cache.seek( a ) );
168 OSL_ASSERT( 1 == cache.seek( b ) );
169 OSL_ASSERT( 0 == cache.seek( c ) );
171 OSL_ASSERT( 1 == cache.put( a ) );
172 OSL_ASSERT( 0xffff == cache.seek( b) );
173 OSL_ASSERT( 1 == cache.seek( a ) );
174 OSL_ASSERT( 0 == cache.seek( c ) );
177 /*******************
178 * Are we within thread, that calls destructors of static objects ?
179 *******************/
180 sal_Bool g_bStaticDestructorsCalled = sal_False;
181 struct StaticSingleton
183 ~StaticSingleton()
185 ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
186 g_bStaticDestructorsCalled = sal_True;
189 StaticSingleton singleton;
191 #if OSL_DEBUG_LEVEL > 1
192 static MyCounter thisCounter( "Remote Environment" );
193 #endif
195 void SAL_CALL allThreadsAreGone( uno_Environment * pEnvRemote )
197 remote_Context *pContext = (remote_Context *) pEnvRemote->pContext;
198 urp_BridgeImpl *pImpl = ( urp_BridgeImpl *) pContext->m_pBridgeImpl;
200 // if the current thread is not the writer thread, the writer thread
201 // object is not destroyed up to now, though it may already have run out.
202 // In both cases, it must be safe to cal pImpl->m_pWriter->getIdentifier()
203 OSL_ASSERT( pImpl->m_pWriter );
204 if( pImpl->m_pWriter->getIdentifier() == osl_getThreadIdentifier(0) )
206 // This is the writer thread. It has done some release calls,
207 // and is now the last one, that was active. Because the writer
208 // thread holds the environment weakly, there may also be a thread within
209 // the dispose of the bridge ( because the enviroment may have a refcount == 0 ).
210 // However, this thread MUST wait for the writer thread, so it is perfectly ok,
211 // not to set m_cndWaitForThreads. ( The check for m_nRemoteThreads is done
212 // after the join of the writer thread ).
214 else
216 pImpl->m_cndWaitForThreads.set();
221 void SAL_CALL releaseStubs( uno_Environment *pEnvRemote )
224 ((remote_Context * ) pEnvRemote->pContext )->m_pBridgeImpl->m_bReleaseStubsCalled = sal_True;
226 remote_Interface **ppInterfaces = 0;
227 sal_Int32 nCount;
228 pEnvRemote->pExtEnv->getRegisteredInterfaces( pEnvRemote->pExtEnv,
229 (void***)&ppInterfaces,
230 &nCount,
231 rtl_allocateMemory );
233 sal_Int32 i;
234 for( i = 0 ; i < nCount ; i ++ )
236 if( ppInterfaces[i]->acquire == bridges_remote::acquireUno2RemoteStub )
238 // these are freed by the environment, so no release necessary
239 pEnvRemote->pExtEnv->revokeInterface( pEnvRemote->pExtEnv, ppInterfaces[i] );
241 else
243 ppInterfaces[i]->release( ppInterfaces[i] );
247 rtl_freeMemory( (void*) ppInterfaces );
250 } // end namespace bridges_urp
252 using namespace bridges_urp;
254 extern "C" {
256 static void SAL_CALL RemoteEnvironment_thisDispose( uno_Environment *pEnvRemote )
258 remote_Context *pContext = (remote_Context *) pEnvRemote->pContext;
259 urp_BridgeImpl *pImpl = ( urp_BridgeImpl *) pContext->m_pBridgeImpl;
261 ::osl::ClearableMutexGuard guard( pImpl->m_disposingMutex );
262 if( pContext->m_pBridgeImpl->m_bDisposed &&
263 ( ! pImpl->m_pReader ||
264 osl_getThreadIdentifier(0) ==
265 (oslThreadIdentifier) pImpl->m_pReader->getIdentifier() ) )
267 return;
269 // in case, that the static destructors already have been called, no
270 // tiding up is done.
271 bool tidyUp;
273 ::osl::MutexGuard guard2( ::osl::Mutex::getGlobalMutex() );
274 tidyUp = ! g_bStaticDestructorsCalled &&
275 ! pContext->m_pBridgeImpl->m_bDisposed;
277 if( tidyUp )
279 // TODO : not threadsafe
280 // synchronization with dispatch methods needed !
282 pImpl->m_bDisposed = sal_True;
285 // close the connection
286 uno_threadpool_dispose( pImpl->m_hThreadPool );
287 pImpl->m_pWriter->abortThread();
288 pContext->m_pConnection->close( pContext->m_pConnection );
290 if( osl_getThreadIdentifier(0) ==
291 (oslThreadIdentifier) pImpl->m_pReader->getIdentifier() )
293 // This is the reader thread. Let the thread destroy itself
294 // the reader thread object must also release the connection at this stage !
295 pImpl->m_pReader->destroyYourself();
296 pImpl->m_pReader = 0;
298 else
300 // wait for the reader thread
301 // the reader thread object must also release the connection,
302 // when terminating !!!!
303 pImpl->m_pReader->join();
306 // wait for the writer thread
307 pImpl->m_pWriter->join();
309 // now let the context go !
310 pContext->dispose( pContext );
312 if( 0 != pImpl->m_nRemoteThreads )
314 // Wait for all threads
315 guard.clear();
316 pImpl->m_cndWaitForThreads.wait();
317 OSL_ASSERT( ! pImpl->m_nRemoteThreads );
319 else
321 guard.clear();
323 #ifdef BRIDGES_URP_PROT
324 if( pImpl->m_pLogFile )
326 fclose( pImpl->m_pLogFile );
327 pImpl->m_pLogFile = 0;
329 #endif
330 #if OSL_DEBUG_LEVEL > 1
331 pImpl->dumpErrors( stderr );
332 #endif
334 // destroy the threads
335 delete pImpl->m_pWriter;
336 pImpl->m_pWriter = 0;
338 if( pImpl->m_pReader != 0 )
340 // This is not the reader thread, so the thread object is deleted
341 delete pImpl->m_pReader;
342 pImpl->m_pReader = 0;
345 bool bReleaseStubs = false;
347 ::osl::MutexGuard guard2( ::osl::Mutex::getGlobalMutex() );
348 bReleaseStubs = !g_bStaticDestructorsCalled;
350 if( bReleaseStubs )
352 releaseStubs( pEnvRemote );
357 static void SAL_CALL RemoteEnvironment_thisDisposing(
358 uno_Environment *pEnvRemote )
360 remote_Context *pContext = (remote_Context * )pEnvRemote->pContext;
361 urp_BridgeImpl *pImpl = ((urp_BridgeImpl*) pContext->m_pBridgeImpl);
364 ::osl::ClearableMutexGuard guard( pImpl->m_disposingMutex );
365 if( ! pImpl->m_bDisposed )
367 guard.clear();
368 urp_sendCloseConnection( pEnvRemote );
369 RemoteEnvironment_thisDispose( pEnvRemote );
372 pImpl->m_pPropertyObject->thisRelease();
373 pImpl->m_pPropertyObject = 0;
375 uno_threadpool_destroy( pImpl->m_hThreadPool );
377 delete pImpl;
378 pContext->aBase.release( (uno_Context * ) pContext );
379 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
380 #if OSL_DEBUG_LEVEL > 1
381 thisCounter.release();
382 #endif
385 static void SAL_CALL RemoteEnvironment_thisComputeObjectIdentifier(
386 uno_ExtEnvironment *, rtl_uString **, void *)
388 OSL_ENSURE( 0, "RemoteEnvironment_thisComputeObjectIdentifier should never be called" );
391 static void SAL_CALL RemoteEnvironment_thisAcquireInterface(
392 uno_ExtEnvironment *, void *pInterface )
394 ((remote_Interface *)pInterface)->acquire( ( remote_Interface *) pInterface );
397 static void SAL_CALL RemoteEnvironment_thisReleaseInterface(
398 uno_ExtEnvironment *, void *pInterface )
400 ((remote_Interface *)pInterface)->release( ( remote_Interface *) pInterface );
403 //##################################################################################################
404 void SAL_CALL uno_initEnvironment( uno_Environment * pEnvRemote )
406 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
407 // set C-virtual methods
408 pEnvRemote->environmentDisposing = RemoteEnvironment_thisDisposing;
409 pEnvRemote->pExtEnv->computeObjectIdentifier = RemoteEnvironment_thisComputeObjectIdentifier;
410 pEnvRemote->pExtEnv->acquireInterface = RemoteEnvironment_thisAcquireInterface;
411 pEnvRemote->pExtEnv->releaseInterface = RemoteEnvironment_thisReleaseInterface;
412 pEnvRemote->dispose = RemoteEnvironment_thisDispose;
414 remote_Context *pContext = ( remote_Context * ) pEnvRemote->pContext;
415 pContext->aBase.acquire( ( uno_Context * ) pContext );
416 pContext->getRemoteInstance = ::bridges_remote::remote_sendQueryInterface;
418 // Initialize impl struct urp_BridgeImpl
419 urp_BridgeImpl *pImpl = new ::bridges_urp::urp_BridgeImpl( 256, 8192 );
420 pContext->m_pBridgeImpl = pImpl;
422 // Initialize threadpool
423 pImpl->m_hThreadPool = uno_threadpool_create();
425 // take the bridgepointer as id
426 pImpl->m_properties.seqBridgeID = ByteSequence( (sal_Int8*)&pEnvRemote , sizeof( pEnvRemote ) );
428 pImpl->m_allThreadsAreGone = allThreadsAreGone;
429 pImpl->m_sendRequest = urp_sendRequest;
430 pImpl->m_nRemoteThreads = 0;
431 pImpl->m_bDisposed = sal_False;
432 pImpl->m_bReleaseStubsCalled = sal_False;
434 pImpl->m_pPropertyObject = new PropertyObject( &(pImpl->m_properties ), pEnvRemote, pImpl );
435 pImpl->m_pPropertyObject->thisAcquire();
437 OUString sProtocolProperties;
438 if( pContext->m_pProtocol->length > 3 )
440 sProtocolProperties = OUString( pContext->m_pProtocol ).copy( 4, pContext->m_pProtocol->length-4);
442 if( sProtocolProperties.getLength() )
444 struct Properties props = pImpl->m_properties;
445 assignFromStringToStruct( sProtocolProperties , &props );
446 if( ! props.bNegotiate )
448 // no negotiation takes place, the creator of the bridge knows the parameter
449 // of the other side !
450 pImpl->applyProtocolChanges( props );
451 sProtocolProperties = OUString();
455 #ifdef BRIDGES_URP_PROT
456 char *p = getenv( "PROT_REMOTE" );
457 pImpl->m_pLogFile = 0;
458 if( p )
460 MutexGuard guard( Mutex::getGlobalMutex() );
461 static int counter;
462 oslProcessInfo data;
463 data.Size = sizeof( data );
464 osl_getProcessInfo( 0 , osl_Process_HEAPUSAGE | osl_Process_IDENTIFIER , &data );
465 OString s(p);
466 s += "_pid";
467 s += OString::valueOf( (sal_Int32) data.Ident );
468 s += "_";
469 s += OString::valueOf( (sal_Int32) counter );
470 pImpl->m_sLogFileName = s;
471 // clear the file
472 FILE *f = fopen( s.getStr() , "w" );
473 OSL_ASSERT( f );
474 if( getenv( "PROT_REMOTE_FAST") )
476 pImpl->m_pLogFile = f;
478 else
480 fclose( f );
482 counter++;
484 #endif
486 // start reader and writer threads
487 pImpl->m_pWriter = new ::bridges_urp::OWriterThread( pContext->m_pConnection , pImpl,
488 pEnvRemote);
489 pImpl->m_pWriter->create();
491 pImpl->m_pReader = new ::bridges_urp::OReaderThread( pContext->m_pConnection ,
492 pEnvRemote,
493 pImpl->m_pWriter );
494 pImpl->m_pReader->create();
496 PropertySetterThread *pPropsSetterThread =
497 new PropertySetterThread( pEnvRemote, pImpl , sProtocolProperties );
498 pPropsSetterThread->create();
499 #if OSL_DEBUG_LEVEL > 1
500 thisCounter.acquire();
501 #endif
505 //##################################################################################################
506 void SAL_CALL uno_ext_getMapping(
507 uno_Mapping ** ppMapping,
508 uno_Environment * pFrom,
509 uno_Environment * pTo )
511 OSL_ASSERT( ppMapping && pFrom && pTo );
512 if (ppMapping && pFrom && pTo)
514 if (*ppMapping)
515 ((*ppMapping)->release)( *ppMapping );
516 bridges_remote::RemoteMapping * pMapping = 0;
518 ::rtl::OUString sFromName = pFrom->pTypeName;
519 ::rtl::OUString sToName = pTo->pTypeName;
520 ::rtl::OUString sUno = OUString::createFromAscii( UNO_LB_UNO );
521 ::rtl::OUString sRemote = OUString::createFromAscii( "urp" );
522 if ( sFromName.equalsIgnoreAsciiCase( sRemote ) &&
523 sToName.equalsIgnoreAsciiCase( sUno ) )
525 pMapping = new bridges_remote::RemoteMapping( pTo, /* Uno */
526 pFrom, /*remote*/
527 bridges_remote::remoteToUno,
528 OUString() );
530 else if ( sFromName.equalsIgnoreAsciiCase( sUno ) &&
531 sToName.equalsIgnoreAsciiCase( sRemote ) )
533 pMapping = new bridges_remote::RemoteMapping( pFrom ,
534 pTo ,
535 bridges_remote::unoToRemote,
536 OUString() );
539 *ppMapping = (uno_Mapping * )pMapping;
540 OUString dummy;
541 uno_registerMapping( ppMapping ,
542 bridges_remote::freeRemoteMapping,
543 pFrom ,
544 pTo ,
545 dummy.pData );
549 sal_Bool SAL_CALL component_canUnload( TimeValue *pTime )
551 return g_moduleCount.canUnload( &g_moduleCount , pTime );