~ubuntu-branches/ubuntu/utopic/python-omniorb/utopic

« back to all changes in this revision

Viewing changes to modules/pyCallDescriptor.cc

  • Committer: Bazaar Package Importer
  • Author(s): Floris Bruynooghe
  • Date: 2008-03-26 22:17:38 UTC
  • Revision ID: james.westby@ubuntu.com-20080326221738-r20t9hmikbvcg2vh
Tags: upstream-3.2
ImportĀ upstreamĀ versionĀ 3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- Mode: C++; -*-
 
2
//                            Package   : omniORBpy
 
3
// pyCallDescriptor.cc        Created on: 2000/02/02
 
4
//                            Author    : Duncan Grisby (dpg1)
 
5
//
 
6
//    Copyright (C) 2000 AT&T Laboratories Cambridge
 
7
//
 
8
//    This file is part of the omniORBpy library
 
9
//
 
10
//    The omniORBpy library is free software; you can redistribute it
 
11
//    and/or modify it under the terms of the GNU Lesser General
 
12
//    Public License as published by the Free Software Foundation;
 
13
//    either version 2.1 of the License, or (at your option) any later
 
14
//    version.
 
15
//
 
16
//    This library is distributed in the hope that it will be useful,
 
17
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
//    GNU Lesser General Public License for more details.
 
20
//
 
21
//    You should have received a copy of the GNU Lesser General Public
 
22
//    License along with this library; if not, write to the Free
 
23
//    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 
24
//    MA 02111-1307, USA
 
25
//
 
26
//
 
27
// Description:
 
28
//    Implementation of Python call descriptor object
 
29
 
 
30
// $Id: pyCallDescriptor.cc,v 1.1.4.3 2005/01/07 00:22:32 dgrisby Exp $
 
31
// $Log: pyCallDescriptor.cc,v $
 
32
// Revision 1.1.4.3  2005/01/07 00:22:32  dgrisby
 
33
// Big merge from omnipy2_develop.
 
34
//
 
35
// Revision 1.1.4.2  2003/07/10 22:17:02  dgrisby
 
36
// Track orb core changes, fix bugs.
 
37
//
 
38
// Revision 1.1.4.1  2003/03/23 21:51:57  dgrisby
 
39
// New omnipy3_develop branch.
 
40
//
 
41
// Revision 1.1.2.11  2003/01/27 11:56:57  dgrisby
 
42
// Correctly handle invalid returns from application code.
 
43
//
 
44
// Revision 1.1.2.10  2002/01/18 15:49:44  dpg1
 
45
// Context support. New system exception construction. Fix None call problem.
 
46
//
 
47
// Revision 1.1.2.9  2001/09/24 10:48:25  dpg1
 
48
// Meaningful minor codes.
 
49
//
 
50
// Revision 1.1.2.8  2001/09/20 14:51:24  dpg1
 
51
// Allow ORB reinitialisation after destroy(). Clean up use of omni namespace.
 
52
//
 
53
// Revision 1.1.2.7  2001/08/15 10:37:14  dpg1
 
54
// Track ORB core object table changes.
 
55
//
 
56
// Revision 1.1.2.6  2001/06/29 15:11:12  dpg1
 
57
// Fix for clients using GIOP 1.0.
 
58
//
 
59
// Revision 1.1.2.5  2001/06/29 09:53:56  dpg1
 
60
// Fix for clients using GIOP 1.0.
 
61
//
 
62
// Revision 1.1.2.4  2001/06/01 11:09:26  dpg1
 
63
// Make use of new omni::ptrStrCmp() and omni::strCmp().
 
64
//
 
65
// Revision 1.1.2.3  2001/05/10 15:16:02  dpg1
 
66
// Big update to support new omniORB 4 internals.
 
67
//
 
68
// Revision 1.1.2.2  2001/01/10 12:00:07  dpg1
 
69
// Release the Python interpreter lock when doing potentially blocking
 
70
// stream calls.
 
71
//
 
72
// Revision 1.1.2.1  2000/10/13 13:55:24  dpg1
 
73
// Initial support for omniORB 4.
 
74
//
 
75
 
 
76
#include <omnipy.h>
 
77
#include <pyThreadCache.h>
 
78
#include <omniORB4/IOP_C.h>
 
79
 
 
80
#ifdef HAS_Cplusplus_Namespace
 
81
namespace {
 
82
#endif
 
83
  class cdLockHolder {
 
84
  public:
 
85
    inline cdLockHolder(omniPy::Py_omniCallDescriptor* cd) : cd_(cd) {
 
86
      cd->reacquireInterpreterLock();
 
87
    }
 
88
    inline ~cdLockHolder() {
 
89
      cd_->releaseInterpreterLock();
 
90
    }
 
91
  private:
 
92
    omniPy::Py_omniCallDescriptor* cd_;
 
93
  };
 
94
#ifdef HAS_Cplusplus_Namespace
 
95
};
 
96
#endif
 
97
 
 
98
 
 
99
OMNI_USING_NAMESPACE(omni)
 
100
 
 
101
 
 
102
omniPy::Py_omniCallDescriptor::~Py_omniCallDescriptor()
 
103
{
 
104
  OMNIORB_ASSERT(!tstate_);
 
105
  Py_XDECREF(args_);
 
106
  Py_XDECREF(result_);
 
107
}
 
108
 
 
109
 
 
110
void
 
111
omniPy::Py_omniCallDescriptor::initialiseCall(cdrStream&)
 
112
{
 
113
  // initialiseCall() is called with the interpreter lock
 
114
  // released. Reacquire it so we can touch the descriptor objects
 
115
  // safely
 
116
  cdLockHolder _l(this);
 
117
 
 
118
  for (int i=0; i < in_l_; i++)
 
119
    omniPy::validateType(PyTuple_GET_ITEM(in_d_,i),
 
120
                         PyTuple_GET_ITEM(args_,i),
 
121
                         CORBA::COMPLETED_NO);
 
122
}
 
123
 
 
124
 
 
125
void
 
126
omniPy::Py_omniCallDescriptor::marshalArguments(cdrStream& stream)
 
127
{
 
128
  int i;
 
129
  if (in_marshal_) {
 
130
    omniORB::logs(25, "Python marshalArguments re-entered.");
 
131
 
 
132
    // marshalArguments can be re-entered when using GIOP 1.0, to
 
133
    // calculate the message size if the message is too big for a
 
134
    // single buffer. In that case, the interpreter lock has been
 
135
    // released by the PyUnlockingCdrStream, meaning the call
 
136
    // descriptor does not have the lock details. We have to use the
 
137
    // thread cache lock.
 
138
 
 
139
    omnipyThreadCache::lock _t;
 
140
 
 
141
    for (i=0; i < in_l_; i++)
 
142
      omniPy::marshalPyObject(stream,
 
143
                              PyTuple_GET_ITEM(in_d_,i),
 
144
                              PyTuple_GET_ITEM(args_,i));
 
145
    if (ctxt_d_)
 
146
      omniPy::marshalContext(stream, ctxt_d_, PyTuple_GET_ITEM(args_, i));
 
147
  }
 
148
  else {
 
149
    cdLockHolder _l(this);
 
150
 
 
151
    in_marshal_ = 1;
 
152
    PyUnlockingCdrStream pystream(stream);
 
153
 
 
154
    try {
 
155
      for (i=0; i < in_l_; i++)
 
156
        omniPy::marshalPyObject(pystream,
 
157
                                PyTuple_GET_ITEM(in_d_,i),
 
158
                                PyTuple_GET_ITEM(args_,i));
 
159
      if (ctxt_d_)
 
160
        omniPy::marshalContext(pystream, ctxt_d_, PyTuple_GET_ITEM(args_, i));
 
161
    }
 
162
    catch (...) {
 
163
      in_marshal_ = 0;
 
164
      throw;
 
165
    }
 
166
    in_marshal_ = 0;
 
167
  }
 
168
}
 
169
 
 
170
 
 
171
void
 
172
omniPy::Py_omniCallDescriptor::unmarshalReturnedValues(cdrStream& stream)
 
173
{
 
174
  if (out_l_ == -1) return;  // Oneway operation
 
175
 
 
176
  cdLockHolder _l(this);
 
177
 
 
178
  if (out_l_ == 0) {
 
179
    Py_INCREF(Py_None);
 
180
    result_ = Py_None;
 
181
  }
 
182
  else {
 
183
    PyUnlockingCdrStream pystream(stream);
 
184
 
 
185
    if (out_l_ == 1)
 
186
      result_ = omniPy::unmarshalPyObject(pystream,
 
187
                                          PyTuple_GET_ITEM(out_d_, 0));
 
188
    else {
 
189
      result_ = PyTuple_New(out_l_);
 
190
      if (!result_)
 
191
        OMNIORB_THROW(NO_MEMORY, 0,
 
192
                      (CORBA::CompletionStatus)stream.completion());
 
193
 
 
194
      for (int i=0; i < out_l_; i++) {
 
195
        PyTuple_SET_ITEM(result_, i,
 
196
                         omniPy::unmarshalPyObject(pystream,
 
197
                                                   PyTuple_GET_ITEM(out_d_,
 
198
                                                                    i)));
 
199
      }
 
200
    }
 
201
  }
 
202
}
 
203
 
 
204
 
 
205
void
 
206
omniPy::Py_omniCallDescriptor::userException(cdrStream& stream,
 
207
                                             IOP_C* iop_client,
 
208
                                             const char* repoId)
 
209
{
 
210
  reacquireInterpreterLock();
 
211
 
 
212
  PyObject* d_o = PyDict_GetItemString(exc_d_, (char*)repoId);
 
213
 
 
214
  if (d_o) { // class, repoId, exc name, name, descriptor, ...
 
215
 
 
216
    try {
 
217
      PyUserException ex(d_o);
 
218
      
 
219
      ex <<= stream;
 
220
      ex._raise();
 
221
    }
 
222
    catch (...) {
 
223
      releaseInterpreterLock();
 
224
      if (iop_client) iop_client->RequestCompleted();
 
225
      throw;
 
226
    }
 
227
    OMNIORB_ASSERT(0); // Never reach here
 
228
  }
 
229
  else {
 
230
    releaseInterpreterLock();
 
231
    if (iop_client) iop_client->RequestCompleted(1);
 
232
    OMNIORB_THROW(UNKNOWN, UNKNOWN_UserException,
 
233
                  (CORBA::CompletionStatus)stream.completion());
 
234
  }
 
235
}
 
236
 
 
237
 
 
238
void
 
239
omniPy::Py_localCallBackFunction(omniCallDescriptor* cd, omniServant* svnt)
 
240
{
 
241
  Py_omniCallDescriptor* pycd = (Py_omniCallDescriptor*)cd;
 
242
  Py_omniServant*        pyos =
 
243
    (Py_omniServant*)svnt->_ptrToInterface(omniPy::string_Py_omniServant);
 
244
 
 
245
  // Unfortunately, we can't use the call descriptor's
 
246
  // reacquireInterpreterLock() function, since this call-back may be
 
247
  // running in a different thread to the creator of the call
 
248
  // descriptor.
 
249
 
 
250
  if (cd->is_upcall()) {
 
251
    omnipyThreadCache::lock _t;
 
252
    pyos->remote_dispatch(pycd);
 
253
  }
 
254
  else {
 
255
    omnipyThreadCache::lock _t;
 
256
    pyos->local_dispatch(pycd);
 
257
  }
 
258
}
 
259
 
 
260
 
 
261
void
 
262
omniPy::Py_omniCallDescriptor::unmarshalArguments(cdrStream& stream)
 
263
{
 
264
  OMNIORB_ASSERT(args_ == 0);
 
265
 
 
266
  omnipyThreadCache::lock _t;
 
267
 
 
268
  if (ctxt_d_)
 
269
    args_ = PyTuple_New(in_l_ + 1);
 
270
  else
 
271
    args_ = PyTuple_New(in_l_);
 
272
 
 
273
 
 
274
  PyUnlockingCdrStream pystream(stream);
 
275
 
 
276
  int i;
 
277
  for (i=0; i < in_l_; i++) {
 
278
    PyTuple_SET_ITEM(args_, i,
 
279
                     omniPy::unmarshalPyObject(pystream,
 
280
                                               PyTuple_GET_ITEM(in_d_, i)));
 
281
  }
 
282
  if (ctxt_d_)
 
283
    PyTuple_SET_ITEM(args_, i, omniPy::unmarshalContext(pystream));
 
284
}
 
285
 
 
286
void
 
287
omniPy::Py_omniCallDescriptor::setAndValidateReturnedValues(PyObject* result)
 
288
{
 
289
  OMNIORB_ASSERT(result_ == 0);
 
290
  result_ = result;
 
291
 
 
292
  if (out_l_ == -1 || out_l_ == 0) {
 
293
    if (result_ != Py_None)
 
294
      OMNIORB_THROW(BAD_PARAM,
 
295
                    BAD_PARAM_WrongPythonType,
 
296
                    CORBA::COMPLETED_MAYBE);
 
297
  }
 
298
  else if (out_l_ == 1) {
 
299
    omniPy::validateType(PyTuple_GET_ITEM(out_d_,0),
 
300
                         result,
 
301
                         CORBA::COMPLETED_MAYBE);
 
302
  }
 
303
  else {
 
304
    if (!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != out_l_)
 
305
      OMNIORB_THROW(BAD_PARAM,
 
306
                    BAD_PARAM_WrongPythonType,
 
307
                    CORBA::COMPLETED_MAYBE);
 
308
 
 
309
    for (int i=0; i < out_l_; i++) {
 
310
      omniPy::validateType(PyTuple_GET_ITEM(out_d_,i),
 
311
                           PyTuple_GET_ITEM(result,i),
 
312
                           CORBA::COMPLETED_MAYBE);
 
313
    }
 
314
  }
 
315
}
 
316
 
 
317
void
 
318
omniPy::Py_omniCallDescriptor::marshalReturnedValues(cdrStream& stream)
 
319
{
 
320
  omnipyThreadCache::lock _t;
 
321
  PyUnlockingCdrStream pystream(stream);
 
322
 
 
323
  if (out_l_ == 1) {
 
324
    omniPy::marshalPyObject(pystream,
 
325
                            PyTuple_GET_ITEM(out_d_, 0),
 
326
                            result_);
 
327
  }
 
328
  else {
 
329
    for (int i=0; i < out_l_; i++) {
 
330
      omniPy::marshalPyObject(pystream,
 
331
                              PyTuple_GET_ITEM(out_d_,i),
 
332
                              PyTuple_GET_ITEM(result_,i));
 
333
    }
 
334
  }
 
335
}