PATCH- Demand-driven object loading

Sai-Lai Lo S.Lo@orl.co.uk
Tue, 17 Feb 1998 15:52:27 GMT


>>>>> Randy Shoup writes:

> My questions are:

> 1.  Has anyone re-applied Matthew's changes to version 2.4.0/2.5.0, or
> implemented a similar object-loading scheme with 2.4.0/2.5.0?

> 2.  What is the expected timeline for adding object-loading into the
> main omniORB branch?  Sai-Lai suggested several months ago that support
> for object-loading with application-defined variable-length object keys
> would be one of the next things in the pipeline after support for Any.

Hi Randy,

Attached is a dynamic object loading scheme we intend to put into the
develop tree soon. The scheme is currently used by one of our projects for
loading objects on demand from an Oracle database. This is not Matthew's
loader but (I think) his code can be attached to the ORB using the hook
provided.

The object loading scheme works as follows:

1. The application defines a single handler and registers with the ORB
   through omniORB::loader::set().
2. Whenever the ORB cannot locate the target object in the current address
   space, it calls the handler registered by the application.
3. The handler is expected to load the object and returns its object
   reference to the ORB. Notice that the object reference could point
   to an object in the current address space or in a different address
   space.
4. The ORB then replies with a LOCATION_FORWARD message to instruct the
   client to retry using the object reference.

The scheme falls short of the ultimate goal of allowing application-defined
variable-length object keys. Sorry, can't give you a time scale at the
moment when variable-length object keys will be supported.

Regards,

Sai-Lai

Here comes the patch:
----------------------------- cut here ---------------------------------


diff -r -c omniORB_2.4.0/include/omniORB2/omniORB.h omniORB_2.4.0_patched/include/omniORB2/omniORB.h
*** omniORB_2.4.0/include/omniORB2/omniORB.h	Fri Dec 12 18:47:23 1997
--- omniORB_2.4.0_patched/include/omniORB2/omniORB.h	Tue Feb 17 15:21:33 1998
***************
*** 297,302 ****
--- 297,340 ----
    ////////////////////////////////////////////////////////////////////////
  
    ////////////////////////////////////////////////////////////////////////
+   //                                                                    //
+   // An application can register a handler for loading objects          //
+   // dynamically. The handler should have the signature:                //
+   //                                                                    //
+   //          omniORB::loader::mapKeyToObject_t                         //
+   //                                                                    //
+   // When the ORB cannot locate the target object in this address space,//
+   // it calls the handler with the object key of the target.            //
+   // The handler is expected to instantiate the object, either in       //
+   // this address space or in another address space, and returns the    //
+   // object reference to the newly instantiated object. The ORB will    //
+   // then reply with a LOCATION_FORWARD message to instruct the client  //
+   // to retry using the object reference returned by the handler.       //
+   // When the handler returns, the ORB assumes ownership of the         //
+   // returned value. It will call CORBA::release() on the returned      //
+   // value when it has finished with it.                                //
+   //                                                                    //
+   // The handler may be called concurrently by multi-threads. Hence it  //
+   // must be thread-safe.                                               //
+   //                                                                    //
+   // If the handler cannot load the target object, it should return     //
+   // CORBA::Object::_nil(). The object will be treated as non-existing. //
+   //                                                                    //
+   // The application registers the handler with the ORB at runtime      //
+   // using omniORB::loader::set(). This function is not thread-safe.    //
+   // Calling this function again will replace the old handler with      //
+   // the new one.                                                       //
+   //                                                                    //
+   class loader {                                                        //
+   public:                                                               //
+     typedef CORBA::Object_ptr (*mapKeyToObject_t) (                     //
+                                        const omniORB::objectKey& key);  //
+                                                                         // 
+     static void set(mapKeyToObject_t NewKeyToObject);                   //
+   };
+   ////////////////////////////////////////////////////////////////////////
+ 
+   ////////////////////////////////////////////////////////////////////////
    // class fatalException                                               //
    //                                                                    //
    // This exception is thrown if a bug inside the omniORB2 runtime is   //

diff -r -c omniORB_2.4.0/src/lib/omniORB2/giopServer.cc omniORB_2.4.0_patched/src/lib/omniORB2/giopServer.cc
*** omniORB_2.4.0/src/lib/omniORB2/giopServer.cc	Tue Dec 23 19:24:35 1997
--- omniORB_2.4.0_patched/src/lib/omniORB2/giopServer.cc	Tue Feb 17 15:23:12 1998
***************
*** 53,58 ****
--- 53,69 ----
  
  size_t  GIOP_Basetypes::max_giop_message_size = 2048 * 1024;
  
+ // Dynamic Object Loading
+ // 
+ static omniORB::loader::mapKeyToObject_t MapKeyToObjectFunction= 0;
+ 
+ void 
+ omniORB::loader::set(omniORB::loader::mapKeyToObject_t NewMapKeyToObject) 
+ {
+   MapKeyToObjectFunction= NewMapKeyToObject;
+ }
+ 
+ 
  static void 
  MarshallSystemException(GIOP_S *s,
  			const GIOP_Basetypes::_SysExceptRepoID &id,
***************
*** 508,513 ****
--- 519,553 ----
      
    }
    catch (const CORBA::OBJECT_NOT_EXIST &ex) {
+ 
+     if (!obj && pd_response_expected && MapKeyToObjectFunction) {
+       // Cannot find the object in the object table. If the application
+       // has registered a loader, do an upcall to locate the object.
+       // If the returned value is not a nil object reference, send a
+       // LOCATION_FORWARD message to the client to instruct it to retry
+       // with the new object reference.
+       //
+       // Limitation: if this invocation is oneway, one cannot reply with
+       //             a LOCATION_FORWARD message, in that case, just
+       //             treat this as a normal OBJECT_NOT_EXIST and let
+       //             the code below to deal with it.
+       //
+       CORBA::Object_var newDestination= MapKeyToObjectFunction(pd_objkey);
+       if (!CORBA::is_nil(newDestination)) {
+ 	// Note that we have completed the object request
+ 	RequestReceived(1); 
+ 	
+ 	// Build and send the location forward message...
+ 	size_t msgsize = (size_t) GIOP_S::ReplyHeaderSize();
+ 	msgsize = CORBA::Object::NP_alignedSize(newDestination, msgsize);
+ 	InitialiseReply(GIOP::LOCATION_FORWARD,(CORBA::ULong)msgsize);
+ 	CORBA::Object::marshalObjRef(newDestination, *this);
+ 	
+ 	// All done...
+ 	ReplyCompleted(); return;
+       }
+     }
+ 
      if (!obj) {
        RequestReceived(1);
        if (!pd_response_expected) {
***************
*** 707,733 ****
      obj = omni::locateObject(omniObjectManager::root(),pd_objkey);
      omni::objectRelease(obj);
      status = GIOP::OBJECT_HERE;
!     // XXX what if the object is relocated. We should do GIOP::OBJECT_FORWARD
!     // as well.
    }
    catch(...) {
      status = GIOP::UNKNOWN_OBJECT;
    }
  
!   WrLock();
!   pd_state = GIOP_S::ReplyIsBeingComposed;
! 
!   size_t bodysize = 8;
!   WrMessageSize(0);
!   put_char_array((CORBA::Char *)MessageHeader::LocateReply,
! 		 sizeof(MessageHeader::LocateReply),1,1);
!   operator>>= ((CORBA::ULong)bodysize,*this);
!   operator>>= (pd_request_id,*this);
!   operator>>= ((CORBA::ULong)status,*this);
  
!   flush(1);
!   pd_state = GIOP_S::Idle;
!   WrUnlock();
  
    return;
  }
--- 747,804 ----
      obj = omni::locateObject(omniObjectManager::root(),pd_objkey);
      omni::objectRelease(obj);
      status = GIOP::OBJECT_HERE;
!   }
!   catch (const CORBA::OBJECT_NOT_EXIST&) {
!     if (MapKeyToObjectFunction) {
!       // Cannot find the object in the object table. If the application
!       // has registered a loader, do an upcall to locate the object.
!       // If the return value is not a nil object reference, reply with
!       // OBJECT_FORWARD and the new object reference.
!       CORBA::Object_var newDestination = MapKeyToObjectFunction(pd_objkey);
!       if (!CORBA::is_nil(newDestination)) {
! 	status = GIOP::OBJECT_FORWARD;
! 	WrLock();
! 	pd_state = GIOP_S::ReplyIsBeingComposed;
! 
! 	size_t msgsize = sizeof(MessageHeader::LocateReply) + 4 + 8;
! 	msgsize = CORBA::Object::NP_alignedSize(newDestination,msgsize);
! 	msgsize = msgsize - sizeof(MessageHeader::LocateReply) - 4;
! 	WrMessageSize(0);
! 	put_char_array((CORBA::Char *)MessageHeader::LocateReply,
! 		       sizeof(MessageHeader::LocateReply),1,1);
! 	operator>>= ((CORBA::ULong)msgsize,*this);
! 	operator>>= (pd_request_id,*this);
! 	operator>>= ((CORBA::ULong)status,*this);
! 	CORBA::Object::marshalObjRef(newDestination,*this);
! 	flush(1);
! 	pd_state = GIOP_S::Idle;
! 	WrUnlock();
!       }
!     }
!     else {
!       status = GIOP::UNKNOWN_OBJECT;
!     }
    }
    catch(...) {
      status = GIOP::UNKNOWN_OBJECT;
    }
  
!   if (status != GIOP::OBJECT_FORWARD) {
!     WrLock();
!     pd_state = GIOP_S::ReplyIsBeingComposed;
! 
!     size_t bodysize = 8;
!     WrMessageSize(0);
!     put_char_array((CORBA::Char *)MessageHeader::LocateReply,
! 		   sizeof(MessageHeader::LocateReply),1,1);
!     operator>>= ((CORBA::ULong)bodysize,*this);
!     operator>>= (pd_request_id,*this);
!     operator>>= ((CORBA::ULong)status,*this);
  
!     flush(1);
!     pd_state = GIOP_S::Idle;
!     WrUnlock();
!   }
  
    return;
  }

---------------------------------------------------------------------------