00001 #define DIMC_MODULE
00002 #include <cctype>
00003 #include <cstdlib>
00004 #include <cstdio>
00005 #include <map>
00006 #include <string>
00007
00008 #ifndef _WIN32
00009 #include <unistd.h>
00010 #include <pthread.h>
00011 #else
00012 #define HOST_NAME_MAX 256
00013 #include <winsock.h>
00014 #endif
00015
00016 extern "C" {
00017 #include <Python.h>
00018 #include "dic.h"
00019 #include "dis.h"
00020 #include "dim_common.h"
00021 }
00022 #include "pydim_utils.cpp"
00023
00024 using namespace std;
00025 static char server_name[HOST_NAME_MAX + 1];
00026 typedef void* func(int*);
00027
00028
00029
00030
00031
00032 typedef struct {
00033 char *name;
00034 char *format;
00035 PyObject *pyTag;
00036 PyObject *pyFunc;
00037 } CmndCallback;
00038 typedef CmndCallback* CmndCallbackPtr;
00039
00040 map<string, CmndCallbackPtr> cmndName2PythonFunc;
00041 map<long, CmndCallbackPtr> cmndUniqueTag2PythonFunc;
00042
00043 typedef struct {
00044 char *name;
00045 char *format;
00046 char *buffer;
00047 unsigned int bufferSize;
00048 bool isUpdated;
00049 bool firstCall;
00050 long pyTag;
00051 PyObject *pyFunc;
00052 } ServiceCallback;
00053
00054 typedef ServiceCallback *ServiceCallbackPtr;
00055 map<unsigned int, ServiceCallbackPtr> serviceID2Callback;
00056
00057 static void dim_callbackCommandFunc(void*, void*, int*);
00058
00059
00060
00061
00062 struct _dic_info_service_callback{
00063 PyObject* pyFunc;
00064 char* name;
00065 char* format;
00066 PyObject* pyDefaultArg;
00067 long pyTag;
00068 int service_id;
00069 };
00070
00071 struct _dic_cmnd_callback {
00072 PyObject* pyFunc;
00073 long pyTag;
00074 };
00075
00076 unsigned long _dic_cmnd_callback_ID;
00077
00078
00079 static map<string,_dic_info_service_callback*>_dic_info_service_name2Callback;
00080 static map<unsigned int, _dic_info_service_callback*>_dic_info_service_id2Callback;
00081 static map<long, _dic_cmnd_callback*> _dic_cmnd_callback_tag2Callback;
00082
00083 void _dic_error_user_routine_dummy(int, int, char*);
00084 void _dic_info_service_dummy (void*, void*, int*);
00085 void _dic_cmnd_callback_dummy(void*, int*);
00086 void _dic_error_user_routine_dummy(int, int, char*);
00087
00088
00089
00090
00091
00092
00093
00094
00095 static PyObject*
00096 dim_dis_start_serving (PyObject* , PyObject *args) {
00097
00098
00099
00100
00101 char *name = NULL;
00102 int ret;
00103
00104 if (!PyArg_ParseTuple(args, "|s", &name)) {
00105 PyErr_SetString(PyExc_RuntimeError, "Invalid server name.");
00106 return NULL;
00107 }
00108 if (name)
00109 strncpy(server_name, name, HOST_NAME_MAX + 1);
00110 else {
00111 gethostname(server_name, HOST_NAME_MAX);
00112 debug("No server name specified. Using machine hostname...\n");
00113 }
00114 Py_BEGIN_ALLOW_THREADS
00115 ret = dis_start_serving(server_name);
00116 Py_END_ALLOW_THREADS
00117
00118 return Py_BuildValue("i", ret);
00119 }
00120
00121 static PyObject*
00122 dim_dis_stop_serving(PyObject* , PyObject* ) {
00123
00124
00125 Py_BEGIN_ALLOW_THREADS
00126 dis_stop_serving();
00127 Py_END_ALLOW_THREADS
00128 Py_RETURN_NONE;
00129 }
00130
00131
00132 static PyObject*
00133 dim_dis_set_dns_node(PyObject* , PyObject* args) {
00134
00135
00136
00137
00138
00139
00140 char* name = NULL;
00141 int ret;
00142
00143 if ( !PyArg_ParseTuple(args, "s", &name) ) {
00144 PyErr_SetString(PyExc_RuntimeError, "Invalid DNS name");
00145 return NULL;
00146 }
00147 ret = dis_set_dns_node(name);
00148
00149 return Py_BuildValue("i", ret);
00150 }
00151
00152
00153 static PyObject*
00154 dim_dis_get_dns_node(PyObject* , PyObject* ) {
00155
00156
00157
00158 char names[256];
00159 if ( !dis_get_dns_node(names) ) {
00160 PyErr_SetString(PyExc_RuntimeError, "Failed to get DNS node name");
00161 return NULL;
00162 }
00163 return Py_BuildValue("s", names);
00164 }
00165
00166
00167 static PyObject*
00168 dim_dis_set_dns_port(PyObject* , PyObject* args) {
00169
00170
00171
00172
00173
00174
00175 unsigned int port;
00176 int ret;
00177
00178 if (!PyArg_ParseTuple(args, "I", &port)) {
00179 PyErr_SetString(PyExc_TypeError,
00180 "Argument 'port' must be a pozitive integer");
00181 return NULL;
00182 }
00183 ret = dis_set_dns_port(port);
00184
00185 return Py_BuildValue("i", ret);
00186 }
00187
00188 static PyObject*
00189 dim_dis_get_dns_port(PyObject* , PyObject* ) {
00190
00191
00192
00193
00194 int port;
00195 port = dis_get_dns_port();
00196 return Py_BuildValue("i", port);
00197 }
00198
00199
00200 typedef struct {
00201 PyObject* self;
00202 PyObject* func;
00203 } PyCallback;
00204
00205 static PyCallback dis_callbackExitHandler_func,
00206 dis_callbackErrorHandler_func,
00207 dis_callbackClientExitHandler_func;
00208
00209 static PyCallback _dic_callback_errorHandler_func;
00210
00211 static void
00212 dim_dis_callbackExitHandler(int* code) {
00213
00214
00215
00216
00217 PyObject *arg, *res;
00218 PyGILState_STATE gstate;
00219
00220 if ( dis_callbackExitHandler_func.func ) {
00221 gstate = PyGILState_Ensure();
00222 arg = Py_BuildValue("i", *code);
00223 res = PyEval_CallObject(dis_callbackExitHandler_func.func, arg);
00224 Py_DECREF(arg);
00225 Py_XDECREF(res);
00226 PyGILState_Release(gstate);
00227 } else {
00228 debug("Could not find any registered Python function. "\
00229 "Dropping DIM exit callback.");
00230 }
00231 }
00232
00233
00234 static void
00235 dim_dis_callbackErrorHandler(int severity, int error_code, char* message) {
00236
00237
00238
00239
00240 PyObject *arg, *res;
00241 PyGILState_STATE gstate;
00242
00243 if (dis_callbackErrorHandler_func.func) {
00244 gstate = PyGILState_Ensure();
00245 arg = Py_BuildValue("iis", severity, error_code, message);
00246 res = PyEval_CallObject(dis_callbackErrorHandler_func.func, arg);
00247 Py_DECREF(arg);
00248 Py_XDECREF(res);
00249 PyGILState_Release(gstate);
00250 } else {
00251 debug("Could not find any registered Python function. "\
00252 "Dropping DIM error callback.");
00253 }
00254 }
00255
00256
00257 static void
00258 dim_dis_callbackClientExitHandler(int* tag) {
00259
00260
00261
00262 PyObject *arg, *res;
00263 PyGILState_STATE gstate;
00264
00265 if (dis_callbackClientExitHandler_func.func) {
00266 gstate = PyGILState_Ensure();
00267 arg = Py_BuildValue("i", *tag);
00268 res = PyEval_CallObject(dis_callbackClientExitHandler_func.func, arg);
00269 Py_DECREF(arg);
00270 Py_XDECREF(res);
00271 PyGILState_Release(gstate);
00272 } else {
00273 debug("Could not find any registered Python function. "\
00274 "Dropping DIM client exit callback.");
00275 }
00276 }
00277
00278
00279 static PyObject*
00280 dim_dis_add_exit_handler(PyObject* self, PyObject* args) {
00281
00282
00283
00284
00285 PyObject *temp;
00286
00287 if (!PyArg_ParseTuple(args, "O:set_callback", &temp) ||
00288 !PyCallable_Check(temp))
00289 {
00290 PyErr_SetString(PyExc_TypeError, "Expected a callable Python object");
00291 return NULL;
00292 }
00293
00294 Py_XINCREF(temp);
00295 Py_XINCREF(self);
00296
00297 Py_XDECREF(dis_callbackExitHandler_func.self);
00298 Py_XDECREF(dis_callbackExitHandler_func.func);
00299 dis_callbackExitHandler_func.self = self;
00300 dis_callbackExitHandler_func.func = temp;
00301 dis_add_exit_handler(dim_dis_callbackExitHandler);
00302
00303 Py_RETURN_NONE;
00304 }
00305
00306
00307 static PyObject*
00308 dim_dis_add_error_handler(PyObject* self, PyObject* args) {
00309
00310
00311
00312
00313 PyObject *temp;
00314
00315 if (!PyArg_ParseTuple(args, "O:set_callback", &temp) ||
00316 !PyCallable_Check(temp))
00317 {
00318 PyErr_SetString(PyExc_TypeError, "Expected a callable Python object");
00319 return NULL;
00320 }
00321
00322 Py_XINCREF(temp);
00323 Py_XINCREF(self);
00324
00325 Py_XDECREF(dis_callbackErrorHandler_func.self);
00326 Py_XDECREF(dis_callbackErrorHandler_func.func);
00327 dis_callbackErrorHandler_func.self = self;
00328 dis_callbackErrorHandler_func.func = temp;
00329 dis_add_error_handler(dim_dis_callbackErrorHandler);
00330
00331 Py_RETURN_NONE;
00332 }
00333
00334 static PyObject*
00335 dim_dis_add_client_exit_handler(PyObject* self, PyObject* args) {
00336
00337
00338
00339
00340 PyObject *temp;
00341
00342 if (!PyArg_ParseTuple(args, "O:set_callback", &temp) ||
00343 !PyCallable_Check(temp))
00344 {
00345 PyErr_SetString(PyExc_TypeError, "Expected a callable Python object");
00346 return NULL;
00347 }
00348
00349 Py_XINCREF(temp);
00350 Py_XINCREF(self);
00351
00352 Py_XDECREF(dis_callbackClientExitHandler_func.self);
00353 Py_XDECREF(dis_callbackClientExitHandler_func.func);
00354 dis_callbackClientExitHandler_func.self = self;
00355 dis_callbackClientExitHandler_func.func = temp;
00356 dis_add_client_exit_handler(dim_dis_callbackClientExitHandler);
00357
00358 Py_RETURN_NONE;
00359 }
00360
00361
00362 static PyObject*
00363 dim_dis_selective_update_service(PyObject* , PyObject* args) {
00364
00365
00366
00367 int* client_ids=NULL, res;
00368 PyObject* listOrTuple;
00369 int service_id;
00370
00371 if (!PyArg_ParseTuple(args, "iO;list or tuple", &service_id, &listOrTuple)) {
00372 PyErr_SetString(PyExc_TypeError,
00373 "Invalid arguments: expected and integer and a list/tuple of integers");
00374 return NULL;
00375 }
00376 if (!listOrTuple2Int(listOrTuple, &client_ids)) {
00377 PyErr_SetString(PyExc_TypeError,
00378 "Second argument must a list/tuple of integers"
00379 );
00380 return NULL;
00381 }
00382 res = dis_selective_update_service(service_id, client_ids);
00383
00384 return Py_BuildValue("i", res);
00385 }
00386
00387
00388 static PyObject*
00389 dim_dis_set_quality(PyObject* , PyObject* args) {
00390
00391
00392
00393
00394
00395 unsigned int service_id;
00396 int quality;
00397
00398 if (!PyArg_ParseTuple(args, "Ii", &service_id, &quality)) {
00399 PyErr_SetString(PyExc_TypeError,
00400 "Invalid arguments: expected an unsigned integer and an integer");
00401 return NULL;
00402 }
00403 dis_set_quality(service_id, quality);
00404
00405 Py_RETURN_NONE;
00406 }
00407
00408
00409 static PyObject*
00410 dim_dis_set_timestamp(PyObject* , PyObject* args) {
00411
00412
00413
00414
00415
00416
00417
00418
00419 unsigned int service_id;
00420 int secs, milisecs;
00421
00422 if (!PyArg_ParseTuple(args, "Iii", &service_id, &secs, &milisecs)) {
00423 PyErr_SetString(PyExc_TypeError,
00424 "Invalid arguments: expected an unsigned integer and two integers");
00425 return NULL;
00426 }
00427 dis_set_timestamp(service_id, secs, milisecs);
00428
00429 Py_RETURN_NONE;
00430 }
00431
00432
00433 static PyObject*
00434 dim_dis_remove_service(PyObject* , PyObject* args) {
00435
00436
00437
00438
00439 unsigned int service_id;
00440 int res;
00441
00442 if ( !PyArg_ParseTuple(args, "I", &service_id) ) {
00443 PyErr_SetString(PyExc_TypeError,
00444 "Invalid argument: expected an unsigned integer");
00445 return NULL;
00446 }
00447 res = dis_remove_service(service_id);
00448
00449 return Py_BuildValue("i", res);
00450 }
00451
00452
00453 static PyObject*
00454 dim_dis_get_next_cmnd(PyObject* , PyObject* args) {
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 int res=0, *buffer, size;
00468 long tag=0;
00469 PyObject* tmp;
00470
00471 if ( !PyArg_ParseTuple(args, "I", &size) ) {
00472 PyErr_SetString(PyExc_TypeError,
00473 "Invalid argument: expected an unsigned integer");
00474 return NULL;
00475 }
00476 buffer = (int*)malloc(size*sizeof(int));
00477 res = dis_get_next_cmnd(&tag, buffer, &size);
00478 tmp = Py_BuildValue("(iis#)", res, tag, buffer, size);
00479 free(buffer);
00480
00481 return tmp;
00482 }
00483
00484
00485 static PyObject*
00486 dim_dis_get_client(PyObject* , PyObject* args) {
00487
00488
00489
00490 char* name; int res;
00491
00492 if ( !PyArg_ParseTuple(args, "s", &name) ) {
00493 PyErr_SetString(PyExc_TypeError, "Invalid argument: expected an string");
00494 return NULL;
00495 }
00496 res = dis_get_client(name);
00497
00498 return Py_BuildValue("i", res);
00499 }
00500
00501
00502 static PyObject*
00503 dim_dis_get_conn_id(PyObject* , PyObject* ) {
00504
00505
00506
00507 int res;
00508 res = dis_get_conn_id();
00509 return Py_BuildValue("i", res);
00510 }
00511
00512
00513 static PyObject*
00514 dim_dis_get_timeout(PyObject* , PyObject* args) {
00515
00516
00517
00518
00519
00520
00521
00522 unsigned int service_id;
00523 int client_id, res;
00524
00525 if ( !PyArg_ParseTuple(args, "Ii", &service_id, &client_id) ) {
00526 PyErr_SetString(PyExc_TypeError,
00527 "Invalid argument: expected an unsigned int and an int");
00528 return NULL;
00529 }
00530 res = dis_get_timeout(service_id, client_id);
00531
00532 return Py_BuildValue("i", res);
00533 }
00534
00535
00536 static PyObject*
00537 dim_dis_get_client_services(PyObject* , PyObject* args) {
00538
00539
00540
00541
00542
00543 char* res=NULL;
00544 int conn_id;
00545
00546 if ( !PyArg_ParseTuple(args, "i", &conn_id) ) {
00547 PyErr_SetString(PyExc_TypeError, "Invalid argument: expected an int");
00548 return NULL;
00549 }
00550 res = dis_get_client_services(conn_id);
00551
00552 return Py_BuildValue("s", res);
00553 }
00554
00555
00556 static PyObject*
00557 dim_dis_set_client_exit_handler(PyObject* , PyObject* args) {
00558
00559
00560
00561 int conn_id, tag;
00562
00563 if ( !PyArg_ParseTuple(args, "ii", &conn_id, &tag) ) {
00564 PyErr_SetString(PyExc_TypeError, "Invalid argument: expected two ints");
00565 return NULL;
00566 }
00567 dis_set_client_exit_handler(conn_id, tag);
00568
00569 Py_RETURN_NONE;
00570 }
00571
00572
00573 static PyObject*
00574 dim_dis_get_error_services(PyObject* , PyObject* ) {
00575
00576
00577
00578 char* res=NULL;
00579 res = dis_get_error_services();
00580 return Py_BuildValue("s", res);
00581 }
00582
00583
00584 static PyObject*
00585 dim_dis_add_cmnd(PyObject* , PyObject* args) {
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 unsigned int res=0;
00608 char *name = NULL, *format = NULL;
00609 PyObject *tag = NULL;
00610 int sizeFormat, sizeName;
00611 PyObject *pyFunc;
00612 CmndCallback *callback, *oldCallback;
00613 string s;
00614
00615 if (!PyArg_ParseTuple(args, "s#s#O|O",
00616 &name, &sizeName, &format, &sizeFormat, &pyFunc, &tag)
00617 || !PyCallable_Check(pyFunc) )
00618 {
00619 PyErr_SetString(PyExc_TypeError,
00620 "Invalid arguments: expected two strings, "
00621 "a callable object and an integer");
00622 return NULL;
00623 }
00624 debug("Adding command name %s, format %s and tag %p", name, format, tag);
00625 callback = (CmndCallback*)malloc(sizeof(CmndCallback));
00626 callback->format = (char*)malloc(sizeof(char)*(sizeFormat+1));
00627 callback->name = (char*)malloc(sizeof(char)*(sizeName+1));
00628 callback->pyFunc = pyFunc;
00629 if (tag) {
00630 Py_INCREF(tag);
00631 callback->pyTag = tag;
00632 }
00633 strcpy(callback->format, format);
00634 strcpy(callback->name, name);
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644 oldCallback = cmndName2PythonFunc[name];
00645 cmndUniqueTag2PythonFunc[(long)callback] = callback;
00646 cmndName2PythonFunc[name] = callback;
00647 res = dis_add_cmnd(name, format, dim_callbackCommandFunc, (long)callback);
00648 if (oldCallback && res<1) {
00649 Py_XDECREF(oldCallback->pyFunc);
00650 Py_XDECREF(oldCallback->pyTag);
00651 free(oldCallback->name);
00652 free(oldCallback->format);
00653 free(oldCallback);
00654 }
00655
00656 return Py_BuildValue("i", res);
00657 }
00658
00659
00660 void
00661 serviceProxy(void *tagp, void **buf, int *size, int * ) {
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688 ServiceCallback* svc =(ServiceCallback*)(*(long *)tagp);
00689
00690 if (!svc->isUpdated || !svc->buffer) {
00691
00692
00693
00694
00695
00696 print("ERROR: You should not see this message! The service update has failed");
00697 debug("Could not get data to update service %s, pointer %x. Output buffer is %x with size %d, updated %d",
00698 svc->name, svc, (long)svc->buffer, svc->bufferSize, svc->isUpdated);
00699 svc->bufferSize = 0;
00700 if (svc->buffer) {
00701 free(svc->buffer);
00702 svc->buffer = NULL;
00703 }
00704 } else if (svc->isUpdated && svc->buffer) {
00705
00706 }
00707 *buf = svc->buffer;
00708 *size = svc->bufferSize;
00709 }
00710
00711
00712 static PyObject*
00713 dim_dis_add_service(PyObject* , PyObject* args) {
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 int name_size, format_size, service_id=0;
00734 char *name, *format;
00735 long pyTag;
00736 PyObject *pyFunc;
00737 ServiceCallback *svc;
00738
00739 if (!PyArg_ParseTuple(args, "s#s#Ol", &name,
00740 &name_size,
00741 &format,
00742 &format_size,
00743 &pyFunc,
00744 &pyTag)
00745 || !PyCallable_Check(pyFunc))
00746 {
00747 PyErr_SetString(PyExc_TypeError,
00748 "Invalid arguments: expected two strings, a callable object and a long.");
00749 return NULL;
00750 }
00751
00752 Py_INCREF(pyFunc);
00753 svc = (ServiceCallback*)malloc(sizeof(ServiceCallback));
00754 svc->name = (char*)malloc(sizeof(char)*(name_size+1));
00755 svc->format = (char*)malloc(sizeof(char)*(format_size+1));
00756 if (!svc || !svc->name || !svc->format) goto noMem;
00757 strcpy(svc->name, name);
00758 strcpy(svc->format, format);
00759 svc->pyTag = pyTag;
00760 svc->pyFunc = pyFunc;
00761 svc->buffer = NULL;
00762 svc->bufferSize = 0;
00763
00764 service_id = dis_add_service(name,
00765 format,
00766 NULL,
00767 0,
00768 serviceProxy,
00769 (long)svc);
00770 if (!service_id) {
00771 PyErr_SetString(PyExc_RuntimeError, "Could not create service");
00772 return NULL;
00773 }
00774
00775 if (serviceID2Callback[service_id]) {
00776
00777 debug("Replacing service %s",svc->name);
00778 Py_XDECREF(serviceID2Callback[service_id]->pyFunc);
00779 free(serviceID2Callback[service_id]->name);
00780 free(serviceID2Callback[service_id]->format);
00781 free(serviceID2Callback[service_id]->buffer);
00782 free(serviceID2Callback[service_id]);
00783 }
00784 serviceID2Callback[service_id] = svc;
00785 debug("Service %s added successfully with pointer %x", svc->name, svc);
00786
00787 return Py_BuildValue("i", service_id);
00788
00789 noMem:
00790 PyErr_SetString(PyExc_MemoryError, "Could not allocate memory");
00791 return NULL;
00792 }
00793
00794
00795 static PyObject*
00796 dim_dis_update_service(PyObject* , PyObject* args) {
00797
00798
00799
00800 int service_id, res;
00801 PyObject *svc_args=NULL, *arg;
00802 ServiceCallbackPtr svc;
00803 PyGILState_STATE gstate;
00804
00805 if ( !PyArg_ParseTuple(args, "i|O", &service_id, &svc_args) ){
00806
00807 PyErr_SetString(PyExc_TypeError,
00808 "Argument error: incorect service ID");
00809 return NULL;
00810 }
00811 svc = serviceID2Callback[service_id];
00812 if (!svc){
00813
00814 PyErr_SetString(PyExc_RuntimeError,
00815 "Service ID doesn't match any service");
00816 return NULL;
00817 }
00818 if (!svc_args) {
00819 if (!svc->pyFunc) {
00820 PyErr_SetString(PyExc_TypeError,
00821 "No arguments and no callback function was given");
00822 return NULL;
00823 }
00824 gstate = PyGILState_Ensure();
00825 arg = Py_BuildValue("(i)", svc->pyTag);
00826 free(svc_args);
00827 svc_args = PyEval_CallObject(svc->pyFunc, arg);
00828 Py_DECREF(arg);
00829
00830 PyGILState_Release(gstate);
00831 if (!svc_args) {
00832
00833
00834
00835
00836 print("Error in calling python function %p", svc->pyFunc);
00837 PyErr_Print();
00838 return NULL;
00839 }
00840 }
00841
00842 if (svc->buffer)
00843 free(svc->buffer);
00844 if (!iterator_to_allocated_buffer(svc_args,
00845 svc->format,
00846 &svc->buffer,
00847 &svc->bufferSize) )
00848 {
00849 PyErr_SetString(PyExc_TypeError,
00850 "Arguments do not match initial service format");
00851 return NULL;
00852 }
00853 Py_DECREF(svc_args);
00854 svc->isUpdated = 1;
00855 Py_BEGIN_ALLOW_THREADS
00856 res = dis_update_service(service_id);
00857 Py_END_ALLOW_THREADS
00858
00859 return Py_BuildValue("i", res);
00860 }
00861
00862
00863 static void
00864 dim_callbackCommandFunc(void* uTag, void* address, int* size) {
00865
00866
00867
00868
00869 CmndCallbackPtr pycall = (CmndCallbackPtr)(*(long *)uTag);
00870 PyObject *args, *res, *funargs;
00871 PyGILState_STATE gstate;
00872
00873 gstate = PyGILState_Ensure();
00874 args = dim_buf_to_tuple(pycall->format, (char*)address, *size);
00875 if (args) {
00876
00877 if (pycall->pyTag) {
00878 funargs = PyTuple_New(2);
00879 PyTuple_SET_ITEM(funargs, 0, args);
00880 PyTuple_SET_ITEM(funargs, 1, pycall->pyTag);
00881 } else {
00882 funargs = PyTuple_New(1);
00883 PyTuple_SET_ITEM(funargs, 0, args);
00884 }
00885 res = PyEval_CallObject(pycall->pyFunc, funargs);
00886 Py_DECREF(args);
00887 Py_DECREF(funargs);
00888 if (!res) {
00889
00890
00891 PyErr_Print();
00892 } else {
00893 Py_DECREF(res);
00894 }
00895 } else {
00896 print ("Could not convert received DIM buffer to Python objects");
00897 }
00898 PyGILState_Release(gstate);
00899 }
00900
00901
00902
00903
00904
00905 static PyObject*
00906 dim_dic_set_dns_node(PyObject* , PyObject* args) {
00907
00908
00909
00910
00911
00912
00913 char* name = NULL;
00914 int i;
00915
00916 if ( !PyArg_ParseTuple(args, "s", &name) ) {
00917 PyErr_SetString(PyExc_TypeError, "Invalid DIM DNS name");
00918 return NULL;
00919 }
00920 i = dic_set_dns_node(name);
00921
00922 return Py_BuildValue("i", i);
00923 }
00924
00925
00926 static PyObject*
00927 dim_dic_get_dns_node(PyObject* , PyObject* ) {
00928
00929
00930
00931 char names[256];
00932
00933 if ( !dic_get_dns_node(names) ) {
00934 PyErr_SetString(PyExc_TypeError,
00935 "Could not get DIM DNS node name.");
00936 return NULL;
00937 }
00938
00939 return Py_BuildValue("s", names);
00940 }
00941
00942
00943 static PyObject*
00944 dim_dic_set_dns_port(PyObject* , PyObject* args) {
00945
00946
00947
00948
00949
00950 unsigned int port;
00951 int i;
00952
00953 if ( !PyArg_ParseTuple(args, "I", &port) ) {
00954 PyErr_SetString(PyExc_TypeError,
00955 "Invalid argument: expected a pozitive integer"
00956 );
00957 return NULL;
00958 }
00959 i = dic_set_dns_port(port);
00960
00961 return Py_BuildValue("i", i);
00962 }
00963
00964
00965 static PyObject*
00966 dim_dic_get_dns_port(PyObject* , PyObject* ) {
00967
00968
00969
00970
00971
00972 int port;
00973 port = dim_get_dns_port();
00974 return Py_BuildValue("i", port);
00975 }
00976
00977
00978 static PyObject*
00979 dim_dic_get_id(PyObject* , PyObject* ) {
00980
00981
00982
00983
00984
00985 char name[256];
00986 int res;
00987
00988 res = dic_get_id(name);
00989 if (!res)
00990 name[0] = 0;
00991
00992 return Py_BuildValue("s", name);
00993 }
00994
00995
00996 static PyObject*
00997 dim_dic_disable_padding(PyObject* , PyObject* ) {
00998
00999
01000
01001
01002 dic_disable_padding();
01003 Py_RETURN_NONE;
01004 }
01005
01006
01007 static PyObject*
01008 dim_dic_get_quality(PyObject* , PyObject* args) {
01009
01010
01011
01012
01013
01014 unsigned int service_id;
01015 int res;
01016
01017 if (!PyArg_ParseTuple(args, "I", &service_id) ) {
01018 PyErr_SetString(PyExc_TypeError,
01019 "Invalid argument: expected an unsigned integer");
01020 return NULL;
01021 }
01022 res = dic_get_quality(service_id);
01023
01024 return Py_BuildValue("i", res);
01025 }
01026
01027
01028 static PyObject*
01029 dim_dic_get_timestamp(PyObject* , PyObject* args) {
01030
01031
01032
01033
01034
01035
01036
01037 unsigned int service_id;
01038 int secs, milisecs=0, res=0;
01039
01040 if (!PyArg_ParseTuple(args, "Iii", &service_id)) {
01041 PyErr_SetString(PyExc_TypeError,
01042 "service id should be an unsigned integer");
01043 return NULL;
01044 }
01045 res = dic_get_timestamp(service_id, &secs, &milisecs);
01046
01047 return Py_BuildValue("ii", secs, milisecs);
01048 }
01049
01050
01051 static PyObject*
01052 dim_dic_get_format(PyObject* , PyObject* args) {
01053
01054
01055
01056
01057
01058 unsigned int service_id;
01059 char* format=NULL;
01060
01061 if (! PyArg_ParseTuple(args, "I", &service_id) ) {
01062 PyErr_SetString(PyExc_TypeError,
01063 "Service id should be an unsigned integer");
01064 return NULL;
01065 }
01066 format = dic_get_format(service_id);
01067
01068 return Py_BuildValue("s", format);
01069 }
01070
01071
01072 static PyObject*
01073 dim_dic_release_service(PyObject* , PyObject* args) {
01074
01075
01076
01077
01078 unsigned int service_id;
01079 string cppName;
01080 _dic_info_service_callback *tmp;
01081
01082 if (!PyArg_ParseTuple(args, "I", &service_id)) {
01083 debug("Invalid service id specified");
01084 PyErr_SetString(PyExc_TypeError,
01085 "Service id should be an unsigned integer");
01086 return NULL;
01087 }
01088 Py_BEGIN_ALLOW_THREADS
01089 dic_release_service(service_id);
01090 Py_END_ALLOW_THREADS
01091 tmp = _dic_info_service_id2Callback[service_id];
01092 cppName = tmp->name;
01093 if (!tmp) {
01094 print("Service with id %d is not known", service_id);
01095 Py_RETURN_NONE;
01096 }
01097 _dic_info_service_name2Callback.erase(cppName);
01098 _dic_info_service_id2Callback.erase(service_id);
01099 free(tmp->format);
01100 free(tmp->name);
01101 Py_XDECREF(tmp->pyFunc);
01102 Py_XDECREF(tmp->pyDefaultArg);
01103 free(tmp);
01104
01105 Py_RETURN_NONE;
01106 }
01107
01108
01109 static PyObject*
01110 dim_dic_info_service(PyObject* , PyObject* args) {
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131 char* name, *format;
01132 int service_type=MONITORED;
01133 int timeout=0;
01134 int tag=0;
01135 int format_size;
01136 int name_size;
01137 unsigned int service_id;
01138 string cppName;
01139 PyObject* pyFunc=NULL, *default_value=NULL ;
01140 _dic_info_service_callback *tmp=NULL, *svc;
01141
01142 if (!PyArg_ParseTuple(args, "s#s#O|iiiO",
01143 &name, &name_size,
01144 &format, &format_size,
01145 &pyFunc,
01146 &service_type,
01147 &timeout,
01148 &tag,
01149 &default_value)
01150 || !PyCallable_Check(pyFunc))
01151 {
01152 goto invalid_args;
01153 }
01154
01155 cppName = name;
01156
01157 Py_INCREF(pyFunc);
01158 if (default_value) Py_INCREF(default_value);
01159
01160
01161
01162 svc = (_dic_info_service_callback*)malloc(sizeof(_dic_info_service_callback));
01163 if (!svc) goto no_memory;
01164 svc->format = (char*)malloc(sizeof(char)*format_size+1);
01165 svc->name = (char*)malloc(sizeof(char)*name_size+1);
01166 if (!svc->format || !svc->name) goto no_memory;
01167 svc->pyDefaultArg = default_value;
01168 svc->pyTag = tag;
01169 svc->pyFunc = pyFunc;
01170 strcpy(svc->name, name);
01171 strcpy(svc->format, format);
01172
01173
01174
01175
01176 Py_BEGIN_ALLOW_THREADS
01177 service_id = dic_info_service(name,
01178 service_type,
01179 timeout,
01180 0, 0,
01181 _dic_info_service_dummy,
01182 (long)svc,
01183 0, 0);
01184 Py_END_ALLOW_THREADS
01185 if (!service_id) {
01186 print("Service %s creation failed. Received result %d", name, service_id);
01187 goto dealocate;
01188 }
01189 svc->service_id = service_id;
01190 tmp = _dic_info_service_name2Callback[cppName];
01191 if (tmp) {
01192 free(tmp->format);
01193 free(tmp->name);
01194 Py_XDECREF(tmp->pyFunc);
01195 Py_XDECREF(tmp->pyDefaultArg);
01196 _dic_info_service_name2Callback.erase(cppName);
01197 _dic_info_service_id2Callback.erase(tmp->service_id);
01198 free(_dic_info_service_name2Callback[cppName]);
01199 }
01200 _dic_info_service_name2Callback[cppName] = svc;
01201 _dic_info_service_id2Callback[service_id] = svc;
01202
01203 return Py_BuildValue("i", service_id);
01204
01205
01206 invalid_args:
01207 PyErr_SetString(PyExc_TypeError,
01208 "Invalid parameters. Expected:string name ,"\
01209 " string format ,"\
01210 " int service_type ,"\
01211 " int timeout ,"\
01212 " PyObject* callbackFunction,"\
01213 " int tag ,"\
01214 " PyObject* default_value"
01215 );
01216 return NULL;
01217
01218
01219 no_memory:
01220 PyErr_SetString(PyExc_MemoryError, "Could not allocate memory");
01221 Py_DECREF(pyFunc);
01222 return NULL;
01223
01224
01225 dealocate:
01226 Py_XDECREF(tmp->pyFunc);
01227 _dic_info_service_name2Callback.erase(cppName);
01228
01229 free(tmp->format);
01230 free(tmp->name);
01231 free(tmp);
01232 return 0;
01233 }
01234
01235
01236 static PyObject*
01237 dim_dic_info_service_stamped(PyObject* self, PyObject* args){
01238
01239
01240
01241
01242
01243
01244
01245 return dim_dic_info_service(self, args);
01246 }
01247
01248
01249 static PyObject*
01250 dim_dic_get_server(PyObject* , PyObject* args) {
01251
01252
01253
01254
01255
01256
01257 int service_id;
01258 char* server_name;
01259
01260 if ( !PyArg_ParseTuple(args, "s", &server_name) ) {
01261 PyErr_SetString(PyExc_TypeError,
01262 "Invalid parameters. Expected argument:string service_name");
01263 return NULL;
01264 }
01265 service_id = dic_get_server(server_name);
01266
01267 return Py_BuildValue("i", service_id);
01268 }
01269
01270
01271 static PyObject*
01272 dim_dic_get_conn_id(PyObject* , PyObject* ) {
01273
01274
01275
01276
01277
01278 int service_id;
01279
01280 service_id = dic_get_conn_id();
01281 return Py_BuildValue("i", service_id);
01282 }
01283
01284
01285 static PyObject*
01286 dim_dic_get_server_services(PyObject* , PyObject* args) {
01287
01288
01289
01290
01291
01292
01293 int conn_id;
01294 char* server_names=NULL;
01295 PyObject* ret;
01296
01297 if (!PyArg_ParseTuple(args, "i", &conn_id)) {
01298 PyErr_SetString(PyExc_TypeError,
01299 "Invalid parameters. Expected argument:int conn_id");
01300 return NULL;
01301 }
01302 server_names = dic_get_server_services(conn_id);
01303 ret = stringList_to_tuple(server_names);
01304
01305 return ret;
01306 }
01307
01308
01309 static PyObject*
01310 dim_dic_get_error_services(PyObject* , PyObject* args) {
01311
01312
01313
01314
01315
01316
01317
01318
01319 char* server_names=NULL;
01320 PyObject* ret;
01321 server_names = dic_get_error_services();
01322 ret = stringList_to_tuple(server_names);
01323 return args;
01324 }
01325
01326
01327 static PyObject*
01328 dim_dic_add_error_handler(PyObject* self, PyObject* args) {
01329
01330
01331
01332
01333
01334
01335 PyObject* pyFunc;
01336
01337 if (!PyArg_ParseTuple(args, "O:set_callback", &pyFunc)
01338 || !PyCallable_Check(pyFunc))
01339 {
01340 PyErr_SetString(PyExc_TypeError,
01341 "Invalid parameters. Expected argument: callable object ");
01342 return NULL;
01343 }
01344 Py_XINCREF(pyFunc);
01345 Py_XINCREF(self);
01346
01347 Py_XDECREF(_dic_callback_errorHandler_func.self);
01348 Py_XDECREF(_dic_callback_errorHandler_func.func);
01349 _dic_callback_errorHandler_func.self = self;
01350 _dic_callback_errorHandler_func.func = pyFunc;
01351
01352 dic_add_error_handler(_dic_error_user_routine_dummy);
01353
01354 Py_RETURN_NONE;
01355 }
01356
01357 static PyObject*
01358 dim_dic_cmnd_service(PyObject* , PyObject* args) {
01359
01360
01361
01362
01363
01364
01365
01366
01367 char *service_name, *format, *buffer;
01368 unsigned int buffer_size;
01369 int res;
01370 PyObject *pySeq;
01371
01372 res = PyArg_ParseTuple(args, "sOs", &service_name, &pySeq, &format);
01373 if (!res)
01374 goto invalid_arguments;
01375
01376 if (!iterator_to_allocated_buffer(pySeq, format, &buffer, &buffer_size))
01377 goto error;
01378 Py_BEGIN_ALLOW_THREADS
01379 res = dic_cmnd_service(service_name, buffer, buffer_size);
01380 Py_END_ALLOW_THREADS
01381
01382 free(buffer);
01383
01384 return Py_BuildValue("i", res);
01385
01386 invalid_arguments:
01387 PyErr_SetString(PyExc_TypeError,
01388 "Invalid parameters. Expected: string service_name (string), "\
01389 "update_data (tuple or list), format (DIM format string)");
01390 return NULL;
01391
01392 error:
01393 PyErr_SetString(PyExc_RuntimeError,
01394 "Could not serialise provided arguments to a DIM buffer.\n"\
01395 "Please check that the order/number "\
01396 "of the argument maches the provided command format.");
01397 free(buffer);
01398 return NULL;
01399
01400 }
01401
01402
01403 static PyObject*
01404 dim_dic_cmnd_callback(PyObject* , PyObject* args) {
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419 char *service_name, *format, *buffer;
01420 unsigned int buffer_size;
01421 int res;
01422 long pyTag;
01423 PyObject *pySeq, *pyFunc;
01424 _dic_cmnd_callback *callback;
01425
01426 if (!PyArg_ParseTuple(args, "sOsOl",
01427 &service_name, &pySeq, &format, &pyFunc, &pyTag)
01428 || !PyCallable_Check(pyFunc))
01429 {
01430 goto invalid_arguments;
01431 }
01432
01433 Py_INCREF(pyFunc);
01434 callback = (_dic_cmnd_callback*)malloc(sizeof(_dic_cmnd_callback));
01435 if (!callback)
01436 goto memory_error;
01437 callback->pyFunc = pyFunc;
01438 callback->pyTag = pyTag;
01439
01440 if (!iterator_to_allocated_buffer(pySeq, format, &buffer, &buffer_size)) {
01441 goto error;
01442 }
01443
01444
01445
01446 Py_BEGIN_ALLOW_THREADS
01447 res = dic_cmnd_callback(service_name,
01448 buffer,
01449 buffer_size,
01450 _dic_cmnd_callback_dummy,
01451 (long)callback);
01452 Py_END_ALLOW_THREADS
01453
01454 free(buffer);
01455
01456 return Py_BuildValue("i", res);
01457
01458 invalid_arguments:
01459 PyErr_SetString(PyExc_TypeError,
01460 "Invalid parameters. "
01461 " Expected: service_name (string), \n"\
01462 " command_data (a tuple or list of values), \n"\
01463 " format (a DIM format string), \n"\
01464 " function_callback (a Python callable object) \n"\
01465 " int tag"
01466 );
01467 return NULL;
01468
01469 error:
01470 PyErr_SetString(PyExc_RuntimeError,
01471 "Could not serialise provided arguments to a DIM buffer.\n"\
01472 "Please check that the order/number "\
01473 "of the argument maches the provided command format.");
01474 return NULL;
01475
01476 memory_error:
01477 PyErr_SetString(PyExc_MemoryError, "Could not allocate memory");
01478 return NULL;
01479 }
01480
01481
01482
01483
01484
01485 void _dic_cmnd_callback_dummy(void *uTag, int* ret_code) {
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497 PyObject* res;
01498 PyGILState_STATE gstate;
01499 _dic_cmnd_callback* callback = (_dic_cmnd_callback *)(*(long *)uTag) ;
01500
01501
01502
01503
01504 gstate = PyGILState_Ensure();
01505 res = pyCallFunction(callback->pyFunc,
01506 Py_BuildValue("li", callback->pyTag, *ret_code));
01507 Py_DECREF(res);
01508 Py_DECREF(callback->pyFunc);
01509 PyGILState_Release(gstate);
01510
01511 free(callback);
01512 }
01513
01514
01515 void _dic_error_user_routine_dummy(int severity, int error_code, char* message) {
01516
01517
01518
01519
01520
01521
01522
01523 PyObject *arg, *res;
01524 PyGILState_STATE gstate;
01525 if ( _dic_callback_errorHandler_func.func ) {
01526 gstate = PyGILState_Ensure();
01527 arg = Py_BuildValue("iis", severity, error_code, message);
01528 res = PyEval_CallObject(_dic_callback_errorHandler_func.func, arg);
01529 Py_DECREF(arg);
01530 Py_XDECREF(res);
01531 PyGILState_Release(gstate);
01532 } else {
01533 debug("Could not find any registered Python function. "\
01534 "Dropping DIM client error callback.");
01535 PyErr_SetString(PyExc_RuntimeError, "Could not find any registered Python function. "\
01536 "Dropping DIM client error callback.");
01537 return;
01538 }
01539 }
01540
01541
01542 void _dic_info_service_dummy (void* tag, void* buffer, int* size) {
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557 PyObject* args, *res;
01558 _dic_info_service_callback* svc;
01559 PyGILState_STATE gstate;
01560
01561
01562
01563 svc = (_dic_info_service_callback*)(*(long *)tag);
01564
01565 gstate = PyGILState_Ensure();
01566 if (!(*size)) {
01567
01568 args = svc->pyDefaultArg;
01569 } else {
01570 args = dim_buf_to_tuple(svc->format, (char*)buffer, *size);
01571 }
01572 if (args) {
01573
01574 res = PyEval_CallObject(svc->pyFunc, args);
01575 if (!res){
01576 if (PyErr_Occurred() != NULL) {
01577 PyErr_Print();
01578 } else {
01579 print("ERROR: Bad call to Python layer");
01580 }
01581 } else {
01582
01583 Py_DECREF(res);
01584 }
01585 Py_XDECREF(args);
01586 } else {
01587
01588 print("ERROR: Could not get new data to update service");
01589 }
01590 PyGILState_Release(gstate);
01591 }
01592
01593
01594
01595
01596 static PyMethodDef DimMethods[] = {
01597 { "dis_start_serving" ,
01598 dim_dis_start_serving ,
01599 METH_VARARGS ,
01600 "Start providing DIM service"
01601 },
01602 { "dis_stop_serving" ,
01603 dim_dis_stop_serving ,
01604 METH_VARARGS ,
01605 "Stop DIM service"
01606 },
01607 { "dis_set_dns_node" ,
01608 dim_dis_set_dns_node ,
01609 METH_VARARGS ,
01610 "Function for setting the DNS node"
01611 },
01612 { "dis_get_dns_node" ,
01613 dim_dis_get_dns_node ,
01614 METH_VARARGS ,
01615 "Function for getting the DNS node"
01616 },
01617 { "dis_set_dns_port" ,
01618 dim_dis_set_dns_port ,
01619 METH_VARARGS ,
01620 "Function for setting the DNS port"
01621 },
01622 { "dis_get_dns_port" ,
01623 dim_dis_get_dns_port ,
01624 METH_VARARGS ,
01625 "Function for getting the DNS port"
01626 },
01627 { "dis_add_exit_handler" ,
01628 dim_dis_add_exit_handler ,
01629 METH_VARARGS ,
01630 "Function for setting the DIM exit handler"
01631 },
01632 { "dis_add_error_handler" ,
01633 dim_dis_add_error_handler ,
01634 METH_VARARGS ,
01635 "Function for setting the DIM error handler"
01636 },
01637 { "dis_add_client_exit_handler" ,
01638 dim_dis_add_client_exit_handler,
01639 METH_VARARGS ,
01640 "Function for setting the DIM Client exit handler"
01641 },
01642 { "dis_update_service" ,
01643 dim_dis_update_service ,
01644 METH_VARARGS ,
01645 "Function for updating the specified service"
01646 },
01647 { "dis_selective_update_service" ,
01648 dim_dis_selective_update_service,
01649 METH_VARARGS ,
01650 "Function for updating the specified service and clients"
01651 },
01652 { "dis_set_quality" ,
01653 dim_dis_set_quality ,
01654 METH_VARARGS ,
01655 "Function for setting the quality of a service"
01656 },
01657 { "dis_set_timestamp" ,
01658 dim_dis_set_timestamp ,
01659 METH_VARARGS ,
01660 "Function for setting the the timestamp of a service"
01661 },
01662 { "dis_remove_service" ,
01663 dim_dis_remove_service ,
01664 METH_VARARGS ,
01665 "Function for removing a service"
01666 },
01667 { "dis_get_next_cmnd" ,
01668 dim_dis_get_next_cmnd ,
01669 METH_VARARGS ,
01670 "Get a command from the list of waiting command requests"
01671 },
01672 { "dis_remove_service" ,
01673 dim_dis_remove_service ,
01674 METH_VARARGS ,
01675 "Remove a Service from the list of provided services"
01676 },
01677 { "dis_get_client" ,
01678 dim_dis_get_client ,
01679 METH_VARARGS ,
01680 "Gets the process identification of the current DIM client"
01681 },
01682 { "dis_get_conn_id" ,
01683 dim_dis_get_conn_id ,
01684 METH_VARARGS ,
01685 "Gets the connection ID of the current DIM client"
01686 },
01687 { "dis_get_timeout" ,
01688 dim_dis_get_timeout ,
01689 METH_VARARGS ,
01690 "Gets the update rate that was specified by a client for a specific service"
01691 },
01692 { "dis_get_client_services" ,
01693 dim_dis_get_client_services ,
01694 METH_VARARGS ,
01695 "Gets the services of a DIM client, which has subscribed to this DIM server"
01696 },
01697 { "dis_set_client_exit_handler" ,
01698 dim_dis_set_client_exit_handler ,
01699 METH_VARARGS ,
01700 "Activates the client exit handler for a specific client and a specific service"
01701 },
01702 { "dis_get_error_services" ,
01703 dim_dis_get_error_services ,
01704 METH_VARARGS ,
01705 "Gets the names of DIM services that have an error"
01706 },
01707 { "dis_add_cmnd" ,
01708 dim_dis_add_cmnd ,
01709 METH_VARARGS ,
01710 "Adds a new command"
01711 },
01712 { "dis_add_service" ,
01713 dim_dis_add_service ,
01714 METH_VARARGS ,
01715 "Adds a new service"
01716 },
01717 { "dic_set_dns_node" ,
01718 dim_dic_set_dns_node ,
01719 METH_VARARGS ,
01720 "Function for setting the DNS node"
01721 },
01722 { "dic_get_dns_node" ,
01723 dim_dic_get_dns_node ,
01724 METH_VARARGS ,
01725 "Function for getting the DNS node"
01726 },
01727 { "dic_set_dns_port" ,
01728 dim_dic_set_dns_port ,
01729 METH_VARARGS ,
01730 "Function for setting the DNS port"
01731 },
01732 { "dic_get_dns_port" ,
01733 dim_dic_get_dns_port ,
01734 METH_VARARGS ,
01735 "Function for getting the DNS port"
01736 },
01737 { "dic_get_id" ,
01738 dim_dic_get_id ,
01739 METH_VARARGS ,
01740 "Gets the process identification of this DIM client."
01741 },
01742 { "dic_disable_padding" ,
01743 dim_dic_disable_padding ,
01744 METH_VARARGS ,
01745 "Disable padding of received services."
01746 },
01747 { "dic_get_quality" ,
01748 dim_dic_get_quality ,
01749 METH_VARARGS ,
01750 "Gets the quality of a received service."
01751 },
01752 { "dic_get_timestamp" ,
01753 dim_dic_get_timestamp ,
01754 METH_VARARGS ,
01755 "Gets the time stamp of a received service."
01756 },
01757 { "dic_get_format" ,
01758 dim_dic_get_format ,
01759 METH_VARARGS ,
01760 "Gets the format description of a received service."
01761 },
01762 { "dic_release_service" ,
01763 dim_dic_release_service ,
01764 METH_VARARGS ,
01765 "Called by a client when a service is not needed anymore."
01766 },
01767 { "dic_info_service" ,
01768 dim_dic_info_service,
01769 METH_VARARGS | METH_KEYWORDS ,
01770 "Called by a client for subscribing to a service."
01771 },
01772 { "dic_cmnd_service" ,
01773 dim_dic_cmnd_service ,
01774 METH_VARARGS ,
01775 "Request the execution of a command by a server."
01776 },
01777 { "dic_cmnd_callback" ,
01778 dim_dic_cmnd_callback ,
01779 METH_VARARGS ,
01780 "Request the execution of a command and registers a completion callback."
01781 },
01782 { "dic_info_service_stamped" ,
01783 dim_dic_info_service_stamped ,
01784 METH_VARARGS ,
01785 "Request a time stamped (and quality flagged) information service from a server"
01786 },
01787 { "dic_get_server" ,
01788 dim_dic_get_server ,
01789 METH_VARARGS ,
01790 "Gets the process identification of the current DIM server"
01791 },
01792 { "dic_get_conn_id" ,
01793 dim_dic_get_conn_id ,
01794 METH_VARARGS ,
01795 "Gets the connection ID of the current DIM server"
01796 },
01797 { "dic_get_server_services" ,
01798 dim_dic_get_server_services ,
01799 METH_VARARGS ,
01800 "Gets the services of a DIM server to which the client has subscribed."
01801 },
01802 { "dic_get_error_services" ,
01803 dim_dic_get_error_services ,
01804 METH_VARARGS ,
01805 "Gets the names of DIM services that have an error."
01806 },
01807 { "dic_add_error_handler" ,
01808 dim_dic_add_error_handler ,
01809 METH_VARARGS ,
01810 "Adds an error handler to this client."
01811 },
01812 {NULL, NULL, 0, NULL}
01813 };
01814
01815 #ifndef _WIN32
01816 static pthread_t maintid;
01817 static pthread_mutex_t pydimlock = PTHREAD_MUTEX_INITIALIZER;
01818 #endif
01819 PyMODINIT_FUNC
01820 initdimc(void)
01821 {
01822 PyObject *m;
01823 PyEval_InitThreads();
01824 debug("Initializing the C DIM interface... \n");
01825 m = Py_InitModule3("dimc", DimMethods, "DIM methods");
01826
01827 if (m == NULL)
01828 return;
01829 #ifndef _WIN32
01830 maintid = pthread_self();
01831 #endif
01832
01833 PyModule_AddIntConstant (m, "ONCE_ONLY", ONCE_ONLY);
01834 PyModule_AddIntConstant (m, "TIMED", TIMED);
01835 PyModule_AddIntConstant (m, "MONITORED", MONITORED);
01836 PyModule_AddIntConstant (m, "COMMAND", COMMAND);
01837 PyModule_AddIntConstant (m, "DIM_DELETE", DIM_DELETE);
01838 PyModule_AddIntConstant (m, "MONIT_ONLY", MONIT_ONLY);
01839 PyModule_AddIntConstant (m, "UPDATE", UPDATE);
01840 PyModule_AddIntConstant (m, "TIMED_ONLY", TIMED_ONLY);
01841 PyModule_AddIntConstant (m, "MONIT_FIRST", MONIT_FIRST);
01842 PyModule_AddIntConstant (m, "MAX_TYPE_DEF", MAX_TYPE_DEF);
01843 PyModule_AddIntConstant (m, "STAMPED", STAMPED);
01844
01845 dic_disable_padding();
01846 dis_disable_padding();
01847 }
01848
01849 #ifdef RINUNX
01850 #include <stdio.h>
01851 #include <dlfcn.h>
01852 #include <errno.h>
01853 #include <string.h>
01854 #include <semaphore.h>
01855
01856 extern sem_t DIM_INIT_Sema;
01857
01858 PyGILState_STATE gilstack[GILSTACKSIZE];
01859 int gilstackp = 0;
01860
01861 void dim_lock()
01862 {
01863 static void (*func)(void);
01864 int v;
01865
01866 if(!func) {
01867 func = (void (*)()) dlsym(RTLD_NEXT, "dim_lock");
01868 if (!func) {
01869 printf("Couldn't find dim_lock");
01870 exit(1);
01871 }
01872 }
01873 if (gilstackp == GILSTACKSIZE) {
01874 printf("ERROR: GILstack overflow");
01875 exit(1);
01876 }
01877 pthread_mutex_lock(&pydimlock);
01878 if ((pthread_self() != maintid)) {
01879 gilstack[gilstackp++] = PyGILState_Ensure();
01880 }
01881 sem_getvalue(&DIM_INIT_Sema, &v);
01882 printf("%d\n", v);
01883 (*func)();
01884 printf("dim_lock() is called: %d\n", gilstackp);
01885 pthread_mutex_unlock(&pydimlock);
01886 return;
01887 }
01888
01889 void dim_unlock()
01890 {
01891
01892 static void (*func)(void);
01893
01894 if(!func) {
01895 func = (void (*)()) dlsym(RTLD_NEXT, "dim_unlock");
01896 if (!func) {
01897 printf("Couldn't find dim_unlock");
01898 exit(1);
01899 }
01900 }
01901
01902 pthread_mutex_lock(&pydimlock);
01903 (*func)();
01904 if ((pthread_self() != maintid)) {
01905 PyGILState_Release(gilstack[gilstackp--]);
01906 }
01907 pthread_mutex_unlock(&pydimlock);
01908 printf("dim_unlock() is called: %d\n", gilstackp);
01909 return;
01910 }
01911
01912 #endif
01913
01914