DCOM-CORBA Comparison Operating Systems II Reference: P. Chung et al., DCOM and CORBA: side by side, step by step,and layer by layer, C++ Report. http://www.research.att.com/~ymwang/papers/HTML/DCOMnCORBA/S.html
A COM object can have multiple interfaces each representing a different view of the object A COM client interacts with a COM object by obtaining a pointer to one of the object's interfaces and invoking methods through that pointer as if the object is in the client's address space
The core of CORBA is the Object Request Broker (ORB) that acts as the software bus over which objects interact with each other transparently The client of a CORBA object acquires an object-reference and uses it as a handle to make calls as if it is in the client's local address space. The ORB is responsible for facilitating the call
Both DCOM and CORBA provides client-server relations between objects The interface to a server is described using an IDL in both cases CORBA supports multiple inheritance at IDL level, DCOM does not DCOM however allows multiple interfaces to an object
Communication CORBA and DCOM uses RPC style of communication The client makes a call to the client stub (called proxy in DCOM) The stub marshals the parameters and sends it to the server At the server end, a server skeleton (called stub in DCOM) demarshals the message and makes the call
Sample application A Grid server maintains a two-dimensional grid of integers Two views to the grid: View One: Two methods: get and set to get and set grid point View Two: One method: reset to reset all grid points to a given value
The DCOM implementation uses two interfaces, one for each view Interfaces IGrid1 and IGrid2 The CORBA implementation uses multiple inheritance Interface grid1 supports get and set Interface grid2 supports reset Interface grid inherits from grid1 and grid2
// uuid and definition of IGrid1 [ object, uuid(3CFDB283-CCC5-11D0-BA0B-00A0C90DF8BC), helpstring("IGrid1 Interface"), pointer_default(unique) ] interface IGrid1 : IUnknown { import "unknwn.idl"; HRESULT get([in] SHORT n, [in] SHORT m, [out] LONG *value); HRESULT set([in] SHORT n, [in] SHORT m, [in] LONG value); }; // uuid and definition of IGrid2 [ object, uuid(3CFDB284-CCC5-11D0-BA0B-00A0C90DF8BC), helpstring("IGrid2 Interface"), pointer_default(unique) ] interface IGrid2 : IUnknown { import "unknwn.idl"; HRESULT reset([in] LONG value); }; DCOM IDL Each interface and class has GUIDs
// uuid and definition of type library [ uuid(3CFDB281-CCC5-11D0-BA0B-00A0C90DF8BC), version(1.0), helpstring("grid 1.0 Type Library) ] library GRIDLib { importlib("stdole32.tlb"); // uuid and definition of class [ uuid(3CFDB287-CCC5-11D0-BA0B-00A0C90DF8BC), helpstring("Grid Class") ] // multiple interfaces coclass CGrid { [default] interface IGrid1; interface IGrid2; }; }; DCOM IDL (continued) multiple views for Grid
interface grid1 { long get(in short n, in short m); void set(in short n, in short m, in long value); }; interface grid2 { void reset(in long value); }; // multiple inheritance of interfaces interface grid: grid1, grid2 { }; CORBA IDL
DCOM server class definition (cgrid.h) #include "grid.h" // IDL-generated interface header file class CGrid : public IGrid1, public IGrid2 { public: // IUnknown STDMETHODIMP QueryInterface(REFIID riid, void** ppv); STDMETHODIMP_(ULONG) AddRef(void) { return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) Release(void) { if (InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; } return 1; } // IGrid1 STDMETHODIMP get(IN SHORT n, IN SHORT m, OUT LONG *value); STDMETHODIMP set(IN SHORT n, IN SHORT m, IN LONG value); // IGrid2 STDMETHODIMP reset(IN LONG value); // create and destroy methods, and private declarations are not shown }
CORBA server class definition (grid_i.h) #include "grid.hh" // IDL-generated interface header file class grid_i : public gridBOAImpl { public: virtual CORBA::Long get(CORBA::Short n, CORBA::Short m, CORBA::Environment &env); virtual void set(CORBA::Short n, CORBA::Short m, CORBA::Long value, CORBA::Environment &env); virtual void reset(CORBA::Long value, CORBA::Environment &env); grid_i(CORBA::Short h, CORBA::Short w); virtual ~grid_i(); private: CORBA::Long **m_a; CORBA::Short m_height, m_width; };
#include &quot;cgrid.h&quot; STDMETHODIMP CGrid::QueryInterface(REFIID riid, void** ppv) { if (riid == IID_IUnknown || riid == IID_IGrid1) *ppv = (IGrid1*) this; else if (riid == IID_IGrid2) *ppv = (IGrid2*) this; else { *ppv = NULL; return E_NOINTERFACE; } AddRef(); return S_OK; } STDMETHODIMP CGrid::get(IN SHORT n, IN SHORT m, OUT LONG* value) { *value = m_a[n][m]; return S_OK; } extern HANDLE hevtDone; CGrid::~CGrid () { for (int i=0; i < m_height; i++) delete[] m_a[i]; delete[] m_a; SetEvent(hevtDone); } DCOM Server Implementation create, set, reset method implementations are not shown
#include &quot;grid_i.h&quot; CORBA::Long grid_i::get(CORBA::Short n, CORBA::Short m, CORBA::Environment &) { return m_a[n][m]; } void grid_i::set(CORBA::Short n, CORBA::Short m, CORBA::Long value, CORBA::Environment &) { m_a[n][m] = value; } void grid_i::reset(CORBA::Long value, CORBA::Environment &) { short n, m; for (n = 0; n < m_height; n++) for (m = 0; m < m_width; m++) m_a[n][m]=value; return; } // create and delete not shown CORBA Server Implementation
HANDLE hevtDone; void main() { // Event used to signal this main thread hevtDone = CreateEvent(NULL, FALSE, FALSE, NULL); hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); CClassFactory* pcf = new CClassFactory; hr = CoRegisterClassObject(CLSID_CGrid, pcf, CLSCTX_SERVER, REGCLS_MULTIPLEUSE , &dwRegister); // Wait until the event is set by CGrid::~CGrid() WaitForSingleObject(hevtDone, INFINITE); CloseHandle(hevtDone); CoUninitialize(); } DCOM Server main program
int main() { // create a grid object using the implementation class grid_i grid_i ourGrid(100,100); try { // tell Orbix that we have completed the server's initialization: CORBA::Orbix.impl_is_ready(&quot;grid&quot;); } catch (...) { cout << &quot;Unexpected exception&quot; << endl; exit(1); } } CORBA Server main program
#include &quot;grid.h&quot; void main(int argc, char**argv) { IGrid1 *pIGrid1; IGrid2 *pIGrid2; LONG value; CoInitialize(NULL); // initialize COM CoCreateInstance(CLSID_CGrid, NULL, CLSCTX_SERVER, IID_IGrid1, (void**) &pIGrid1); pIGrid1->get(0, 0, &value); pIGrid1->QueryInterface(IID_IGrid2, (void**) &pIGrid2); pIGrid1->Release(); pIGrid2->reset(value+1); pIGrid2->Release(); CoUninitialize(); } DCOM client program
CORBA client program #include &quot;grid.hh&quot; void main (int argc, char **argv) { grid_var gridVar; CORBA::Long value; // bind to &quot;grid&quot; object; Orbix-specific gridVar = grid::_bind(&quot;:grid&quot;); value = gridVar->get(0, 0); gridVar->reset(value+1); }
Registration In both CORBA and DCOM the servers need to be registered This establishes the mapping between the interface name and the path name (in CORBA), and the CLSID and the path name in DCOM DCOM uses registry (which is supported by the Window o/s) CORBA uses implementation repository
Observations DCOM: Client calls COM library's CoCreateInstance() with CLSID_Grid and IID_IGrid1 CORBA: Client calls client stub's bind DCOM: The client can get another interface (IID_IGrid2) of the same object using QueryInterface
DCOM Middle layer Upon receiving CoCreateInstance() call, COM library delegates the task to Service Control Manager (SCM) SCM tries to map CLSID_Grid to its server path name by consulting the registry If an instance does not exist, SCM creates an instance When the instance is created, COM creates an interface stub for IID_Grid1 interface Then SCM ferries the marshalled pointer back to the client side; COM on the client side creates a proxy for the interface and associates it the with the RPC channel to the stub COM library returns to the client an IID_IGrid1 pointer to the interface proxy pIGrid1
CORBA middle layer Upon receiving bind() call, the client stub delegates the task to ORB ORB consults the implementation repository and activates the server Server instantiates all supported objects and creates an instance of the skeleton When the ORB ferries the object reference back to the client side, it creastes an instance of the proxy class and registers it in a proxy object table with its corresponding object reference Client stub returns to the client an object reference as gridVar

DCOM Comparison

  • 1.
    DCOM-CORBA Comparison OperatingSystems II Reference: P. Chung et al., DCOM and CORBA: side by side, step by step,and layer by layer, C++ Report. http://www.research.att.com/~ymwang/papers/HTML/DCOMnCORBA/S.html
  • 2.
    A COM objectcan have multiple interfaces each representing a different view of the object A COM client interacts with a COM object by obtaining a pointer to one of the object's interfaces and invoking methods through that pointer as if the object is in the client's address space
  • 3.
    The core ofCORBA is the Object Request Broker (ORB) that acts as the software bus over which objects interact with each other transparently The client of a CORBA object acquires an object-reference and uses it as a handle to make calls as if it is in the client's local address space. The ORB is responsible for facilitating the call
  • 4.
    Both DCOM andCORBA provides client-server relations between objects The interface to a server is described using an IDL in both cases CORBA supports multiple inheritance at IDL level, DCOM does not DCOM however allows multiple interfaces to an object
  • 5.
    Communication CORBA andDCOM uses RPC style of communication The client makes a call to the client stub (called proxy in DCOM) The stub marshals the parameters and sends it to the server At the server end, a server skeleton (called stub in DCOM) demarshals the message and makes the call
  • 6.
    Sample application AGrid server maintains a two-dimensional grid of integers Two views to the grid: View One: Two methods: get and set to get and set grid point View Two: One method: reset to reset all grid points to a given value
  • 7.
    The DCOM implementationuses two interfaces, one for each view Interfaces IGrid1 and IGrid2 The CORBA implementation uses multiple inheritance Interface grid1 supports get and set Interface grid2 supports reset Interface grid inherits from grid1 and grid2
  • 8.
    // uuid anddefinition of IGrid1 [ object, uuid(3CFDB283-CCC5-11D0-BA0B-00A0C90DF8BC), helpstring(&quot;IGrid1 Interface&quot;), pointer_default(unique) ] interface IGrid1 : IUnknown { import &quot;unknwn.idl&quot;; HRESULT get([in] SHORT n, [in] SHORT m, [out] LONG *value); HRESULT set([in] SHORT n, [in] SHORT m, [in] LONG value); }; // uuid and definition of IGrid2 [ object, uuid(3CFDB284-CCC5-11D0-BA0B-00A0C90DF8BC), helpstring(&quot;IGrid2 Interface&quot;), pointer_default(unique) ] interface IGrid2 : IUnknown { import &quot;unknwn.idl&quot;; HRESULT reset([in] LONG value); }; DCOM IDL Each interface and class has GUIDs
  • 9.
    // uuid anddefinition of type library [ uuid(3CFDB281-CCC5-11D0-BA0B-00A0C90DF8BC), version(1.0), helpstring(&quot;grid 1.0 Type Library) ] library GRIDLib { importlib(&quot;stdole32.tlb&quot;); // uuid and definition of class [ uuid(3CFDB287-CCC5-11D0-BA0B-00A0C90DF8BC), helpstring(&quot;Grid Class&quot;) ] // multiple interfaces coclass CGrid { [default] interface IGrid1; interface IGrid2; }; }; DCOM IDL (continued) multiple views for Grid
  • 10.
    interface grid1 { long get(in short n, in short m); void set(in short n, in short m, in long value); }; interface grid2 { void reset(in long value); }; // multiple inheritance of interfaces interface grid: grid1, grid2 { }; CORBA IDL
  • 11.
    DCOM server classdefinition (cgrid.h) #include &quot;grid.h&quot; // IDL-generated interface header file class CGrid : public IGrid1, public IGrid2 { public: // IUnknown STDMETHODIMP QueryInterface(REFIID riid, void** ppv); STDMETHODIMP_(ULONG) AddRef(void) { return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) Release(void) { if (InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; } return 1; } // IGrid1 STDMETHODIMP get(IN SHORT n, IN SHORT m, OUT LONG *value); STDMETHODIMP set(IN SHORT n, IN SHORT m, IN LONG value); // IGrid2 STDMETHODIMP reset(IN LONG value); // create and destroy methods, and private declarations are not shown }
  • 12.
    CORBA server classdefinition (grid_i.h) #include &quot;grid.hh&quot; // IDL-generated interface header file class grid_i : public gridBOAImpl { public: virtual CORBA::Long get(CORBA::Short n, CORBA::Short m, CORBA::Environment &env); virtual void set(CORBA::Short n, CORBA::Short m, CORBA::Long value, CORBA::Environment &env); virtual void reset(CORBA::Long value, CORBA::Environment &env); grid_i(CORBA::Short h, CORBA::Short w); virtual ~grid_i(); private: CORBA::Long **m_a; CORBA::Short m_height, m_width; };
  • 13.
    #include &quot;cgrid.h&quot; STDMETHODIMPCGrid::QueryInterface(REFIID riid, void** ppv) { if (riid == IID_IUnknown || riid == IID_IGrid1) *ppv = (IGrid1*) this; else if (riid == IID_IGrid2) *ppv = (IGrid2*) this; else { *ppv = NULL; return E_NOINTERFACE; } AddRef(); return S_OK; } STDMETHODIMP CGrid::get(IN SHORT n, IN SHORT m, OUT LONG* value) { *value = m_a[n][m]; return S_OK; } extern HANDLE hevtDone; CGrid::~CGrid () { for (int i=0; i < m_height; i++) delete[] m_a[i]; delete[] m_a; SetEvent(hevtDone); } DCOM Server Implementation create, set, reset method implementations are not shown
  • 14.
    #include &quot;grid_i.h&quot; CORBA::Longgrid_i::get(CORBA::Short n, CORBA::Short m, CORBA::Environment &) { return m_a[n][m]; } void grid_i::set(CORBA::Short n, CORBA::Short m, CORBA::Long value, CORBA::Environment &) { m_a[n][m] = value; } void grid_i::reset(CORBA::Long value, CORBA::Environment &) { short n, m; for (n = 0; n < m_height; n++) for (m = 0; m < m_width; m++) m_a[n][m]=value; return; } // create and delete not shown CORBA Server Implementation
  • 15.
    HANDLE hevtDone; voidmain() { // Event used to signal this main thread hevtDone = CreateEvent(NULL, FALSE, FALSE, NULL); hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); CClassFactory* pcf = new CClassFactory; hr = CoRegisterClassObject(CLSID_CGrid, pcf, CLSCTX_SERVER, REGCLS_MULTIPLEUSE , &dwRegister); // Wait until the event is set by CGrid::~CGrid() WaitForSingleObject(hevtDone, INFINITE); CloseHandle(hevtDone); CoUninitialize(); } DCOM Server main program
  • 16.
    int main() { // create a grid object using the implementation class grid_i grid_i ourGrid(100,100); try { // tell Orbix that we have completed the server's initialization: CORBA::Orbix.impl_is_ready(&quot;grid&quot;); } catch (...) { cout << &quot;Unexpected exception&quot; << endl; exit(1); } } CORBA Server main program
  • 17.
    #include &quot;grid.h&quot; voidmain(int argc, char**argv) { IGrid1 *pIGrid1; IGrid2 *pIGrid2; LONG value; CoInitialize(NULL); // initialize COM CoCreateInstance(CLSID_CGrid, NULL, CLSCTX_SERVER, IID_IGrid1, (void**) &pIGrid1); pIGrid1->get(0, 0, &value); pIGrid1->QueryInterface(IID_IGrid2, (void**) &pIGrid2); pIGrid1->Release(); pIGrid2->reset(value+1); pIGrid2->Release(); CoUninitialize(); } DCOM client program
  • 18.
    CORBA client program#include &quot;grid.hh&quot; void main (int argc, char **argv) { grid_var gridVar; CORBA::Long value; // bind to &quot;grid&quot; object; Orbix-specific gridVar = grid::_bind(&quot;:grid&quot;); value = gridVar->get(0, 0); gridVar->reset(value+1); }
  • 19.
    Registration In bothCORBA and DCOM the servers need to be registered This establishes the mapping between the interface name and the path name (in CORBA), and the CLSID and the path name in DCOM DCOM uses registry (which is supported by the Window o/s) CORBA uses implementation repository
  • 20.
    Observations DCOM: Clientcalls COM library's CoCreateInstance() with CLSID_Grid and IID_IGrid1 CORBA: Client calls client stub's bind DCOM: The client can get another interface (IID_IGrid2) of the same object using QueryInterface
  • 21.
    DCOM Middle layerUpon receiving CoCreateInstance() call, COM library delegates the task to Service Control Manager (SCM) SCM tries to map CLSID_Grid to its server path name by consulting the registry If an instance does not exist, SCM creates an instance When the instance is created, COM creates an interface stub for IID_Grid1 interface Then SCM ferries the marshalled pointer back to the client side; COM on the client side creates a proxy for the interface and associates it the with the RPC channel to the stub COM library returns to the client an IID_IGrid1 pointer to the interface proxy pIGrid1
  • 22.
    CORBA middle layerUpon receiving bind() call, the client stub delegates the task to ORB ORB consults the implementation repository and activates the server Server instantiates all supported objects and creates an instance of the skeleton When the ORB ferries the object reference back to the client side, it creastes an instance of the proxy class and registers it in a proxy object table with its corresponding object reference Client stub returns to the client an object reference as gridVar