summaryrefslogtreecommitdiff
path: root/TAO/IIOP/lib/bridge/iiopobj.cpp
blob: ba108478c72d87bbf19b2c64dc6f459db1cfd4e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// @(#)iiopobj.cpp	1.9 95/11/04
// Copyright 1995 by Sun Microsystems Inc.
// All Rights Reserved
//
// IIOP Bridge:		CORBA::Object operations
//
// Some CORBA::Object and other operations are specific to this IIOP
// based implementation, and can neither be used by other kinds of objref
// nor have a default implementation. 
//

#include	<assert.h>
#include	<limits.h>
#include	<corba/orb.hh>

#include	<initguid.h>
#include	<string.h>

#include	<corba/stub.hh>

#include	"runtime/thread.hh"

#include	"bridge/iiopobj.hh"


#ifdef	_POSIX_THREADS
//
// If POSIX threads are available, set up lock covering refcounts.
//
static pthread_mutex_t		iiopobj_lock = PTHREAD_MUTEX_INITIALIZER;
#endif	// _POSIX_THREADS



IIOP::ProfileBody::ProfileBody (
    const IIOP::ProfileBody	&src
) :
    iiop_version		(src.iiop_version),
    port			(src.port)
{
    assert (src.iiop_version.major == MY_MAJOR);
    assert (src.iiop_version.minor == MY_MINOR);

    host = strdup (src.host);

    object_key.length = object_key.maximum = src.object_key.length;
    object_key.buffer = (CORBA_Octet *) malloc (object_key.maximum);
    (void) memcpy (object_key.buffer, src.object_key.buffer,
    		object_key.length);
}


//
// Quick'n'dirty hash of objref data, for partitioning objrefs into sets
//
// NOTE that this must NOT go across the network!
//
CORBA_ULong
IIOP_Object::hash (
    CORBA_ULong			max,
    CORBA_Environment		&env
)
{
    CORBA_ULong	hashval;

    env.clear ();

    //
    // Just grab a bunch of convenient bytes and hash them; could do
    // more (hostname, full key, exponential hashing) but no real need
    // to do so except if performance requires a more costly hash.
    //
    hashval = profile.object_key.length * profile.port;
    hashval += profile.iiop_version.minor;
    if (profile.object_key.length >= 4) {
	hashval += profile.object_key.buffer [1];
	hashval += profile.object_key.buffer [3];
    }
    
    return hashval % max;
}


//
// Expensive comparison of objref data, to see if two objrefs certainly
// point at the same object.  (It's quite OK for this to return FALSE,
// and yet have the two objrefs really point to the same object.)
//
// NOTE that this must NOT go across the network!
//
CORBA_Boolean
IIOP_Object::is_equivalent (
    CORBA_Object_ptr		other_obj,
    CORBA_Environment		&env
)
{
    IIOP::ProfileBody	*body, *body2;
    IIOP_Object		*other_iiop_obj;

    env.clear ();

    if (CORBA_is_nil (other_obj) == CORBA_B_TRUE
	    || other_obj->QueryInterface (IID_IIOP_Object,
			(void **)&other_iiop_obj) != NOERROR)
	return CORBA_B_FALSE;
    CORBA_release (other_obj);

    //
    // Compare all the bytes of the object address -- must be the same
    //
    body = &profile;
    body2 = &other_iiop_obj->profile;

    assert (body->object_key.length < UINT_MAX);

    return body->object_key.length == body2->object_key.length
	    && memcmp (body->object_key.buffer, body2->object_key.buffer,
		    (size_t) body->object_key.length) == 0
	    && body->port == body2->port
	    && strcmp ((char *)body->host, (char *)body2->host) == 0
	    && body->iiop_version.minor == body2->iiop_version.minor
	    && body->iiop_version.major == body2->iiop_version.major;
}


//
// For COM -- IUnknown operations
//

// {A201E4C3-F258-11ce-9598-0000C07CA898}
DEFINE_GUID (IID_IIOP_Object,
0xa201e4c3, 0xf258, 0x11ce, 0x95, 0x98, 0x0, 0x0, 0xc0, 0x7c, 0xa8, 0x98);


ULONG
__stdcall
IIOP_Object::AddRef ()
{
#ifdef	_POSIX_THREADS
    Critical		region (&iiopobj_lock);
#endif

    return ++_refcount;
}

ULONG
__stdcall
IIOP_Object::Release ()
{
#ifdef	_POSIX_THREADS
    Critical		region (&iiopobj_lock);
#endif

    if (--_refcount != 0)
	return _refcount;

#ifdef	_POSIX_THREADS
    region.leave ();
#endif

    delete this;
    return 0;
}


//
// Note that (as of this writing) this is the only place all
// the interfaces to an "objref" come together:
//
// IUnknown ... this one
// STUB_OBJECT ... inherited by this one
// IIOP_OBJECT ... this one
//
// CORBA_Object ... contained within this; it delegates back
//	to this one as its "parent"
//
HRESULT
__stdcall
IIOP_Object::QueryInterface (
    REFIID	riid,
    void	**ppv
)
{
    *ppv = 0;

    if (IID_IIOP_Object == riid
	    || IID_STUB_Object == riid
	    || IID_IUnknown == riid)
	*ppv = this;
    else if (IID_CORBA_Object == riid)
	*ppv = &base;

    if (*ppv == 0)
	return ResultFromScode (E_NOINTERFACE);

    (void) AddRef ();
    return NOERROR;
}