diff --git a/devsupApp/src/dbdset.c b/devsupApp/src/dbdset.c index 9fd4ea3..12461d9 100644 --- a/devsupApp/src/dbdset.c +++ b/devsupApp/src/dbdset.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "pydevsup.h" @@ -31,6 +32,9 @@ typedef struct { PyObject *pyrecord; PyObject *support; + int allowscan; + IOSCANPVT scan; + PyObject *reason; } pyDevice; @@ -49,6 +53,7 @@ static long parse_link(dbCommon *prec, const char* src) return -1; if(!PyArg_ParseTuple(ret, "OO", &priv->pyrecord, &priv->support)) { + priv->pyrecord = priv->support = NULL; /* paranoia */ Py_DECREF(ret); return -1; } @@ -98,6 +103,20 @@ static long process_common(dbCommon *prec) return 0; } +static int allow_ioscan(pyDevice *priv) +{ + PyObject *ret = PyObject_CallMethod(priv->support, "allowScan", "O", priv->pyrecord); + if(!ret || !PyObject_IsTrue(ret)) { + PyErr_Print(); + PyErr_Clear(); + Py_XDECREF(ret); + return 0; + } else { + Py_DECREF(ret); + return 1; + } +} + static long init_record(dbCommon *prec) { return 0; @@ -146,6 +165,7 @@ static long add_record(dbCommon *prec) priv = callocMustSucceed(1, sizeof(*priv), "init_record"); priv->precord = prec; priv->plink = ent.pfield; + scanIoInit(&priv->scan); if(priv->plink->type != INST_IO) { fprintf(stderr, "%s: Has invalid link type %d\n", prec->name, priv->plink->type); @@ -194,7 +214,7 @@ static long del_record(dbCommon *prec) pyDevice *priv=prec->dpvt; PyGILState_STATE pystate; - if(!priv) + if(!priv || !priv->support) return 0; pystate = PyGILState_Ensure(); @@ -212,6 +232,22 @@ static long del_record(dbCommon *prec) return 0; } +static long get_iointr_info(int dir, dbCommon *prec, IOSCANPVT *scan) +{ + pyDevice *priv=prec->dpvt; + if(!priv || !priv->support) + return 0; + + if(dir==0) { + if(!allow_ioscan(priv)) + return S_db_Blocked; + priv->allowscan = 1; + } else + priv->allowscan = 0; + *scan = priv->scan; + return 0; +} + static long process_record(dbCommon *prec) { pyDevice *priv = prec->dpvt; @@ -273,14 +309,28 @@ typedef struct { DEVSUPFUN proc; } dset5; -static dset5 pydevsupCom = {{5, NULL, (DEVSUPFUN)&init, (DEVSUPFUN)&init_record, NULL}, (DEVSUPFUN)&process_record}; -static dset5 pydevsupCom2 = {{5, NULL, (DEVSUPFUN)&init, (DEVSUPFUN)&init_record2, NULL}, (DEVSUPFUN)&process_record}; +static dset5 pydevsupCom = {{5, NULL, (DEVSUPFUN)&init, + (DEVSUPFUN)&init_record, + (DEVSUPFUN)&get_iointr_info}, + (DEVSUPFUN)&process_record}; +static dset5 pydevsupCom2 = {{5, NULL, (DEVSUPFUN)&init, + (DEVSUPFUN)&init_record2, + (DEVSUPFUN)&get_iointr_info}, + (DEVSUPFUN)&process_record}; int isPyRecord(dbCommon *prec) { return prec->dset==(dset*)&pydevsupCom || prec->dset==(dset*)&pydevsupCom2; } +int canIOScanRecord(dbCommon *prec) +{ + pyDevice *priv=prec->dpvt; + if(isPyRecord(prec)) + return 0; + return priv->allowscan; +} + /* Called with GIL locked */ void pyDBD_cleanup(void) { @@ -300,12 +350,9 @@ void pyDBD_cleanup(void) /* cleanup and dealloc */ - if(priv->support) - Py_DECREF(priv->support); - if(priv->pyrecord) - Py_DECREF(priv->pyrecord); - if(priv->reason) - Py_DECREF(priv->reason); + Py_XDECREF(priv->support); + Py_XDECREF(priv->pyrecord); + Py_XDECREF(priv->reason); priv->support = priv->pyrecord = priv->reason = NULL; free(priv); diff --git a/devsupApp/src/dbrec.c b/devsupApp/src/dbrec.c index b6e0d92..714d8f5 100644 --- a/devsupApp/src/dbrec.c +++ b/devsupApp/src/dbrec.c @@ -18,6 +18,7 @@ typedef struct { PyObject_HEAD DBENTRY entry; + int ispyrec; } pyRecord; static void pyRecord_dealloc(pyRecord *self) @@ -33,6 +34,7 @@ static PyObject* pyRecord_new(PyTypeObject *type, PyObject *args, PyObject *kws) self = (pyRecord*)type->tp_alloc(type, 0); if(self) { dbInitEntry(pdbbase, &self->entry); + self->ispyrec = isPyRecord(self->entry.precnode->precord); } return (PyObject*)self; } @@ -50,6 +52,11 @@ static int pyRecord_Init(pyRecord *self, PyObject *args, PyObject *kws) return 0; } +static PyObject* pyRecord_ispyrec(pyRecord *self) +{ + return PyBool_FromLong(self->ispyrec); +} + static int pyRecord_compare(pyRecord *A, pyRecord *B) { dbCommon *a=A->entry.precnode->precord, @@ -124,11 +131,12 @@ static PyObject* pyRecord_scan(pyRecord *self, PyObject *args, PyObject *kws) { dbCommon *prec = self->entry.precnode->precord; - static char* names[] = {"sync", "reason", NULL}; + static char* names[] = {"sync", "reason", "force", NULL}; + unsigned int force = 0; PyObject *reason = Py_None; PyObject *sync = Py_False; - if(!PyArg_ParseTupleAndKeywords(args, kws, "|OO", names, &sync, &reason)) + if(!PyArg_ParseTupleAndKeywords(args, kws, "|OOI", names, &sync, &reason, &force)) return NULL; if(!PyObject_IsTrue(sync)) { @@ -136,20 +144,32 @@ static PyObject* pyRecord_scan(pyRecord *self, PyObject *args, PyObject *kws) Py_RETURN_NONE; } else { - long ret; + long ret=-1; + int ran=1; setReasonPyRecord(prec, reason); Py_BEGIN_ALLOW_THREADS { dbScanLock(prec); - ret = dbProcess(prec); + if(force==1 + || (force==0 && prec->scan==menuScanPassive) + || (force==2 && prec->scan==menuScanI_O_Intr && canIOScanRecord(prec))) + { + ran = 1; + ret = dbProcess(prec); + } dbScanUnlock(prec); } Py_END_ALLOW_THREADS clearReasonPyRecord(prec); - return PyLong_FromLong(ret); + if(ran) + return PyLong_FromLong(ret); + else { + PyErr_SetNone(PyExc_RuntimeError); + return NULL; + } } } @@ -181,7 +201,7 @@ static PyObject *pyRecord_asyncFinish(pyRecord *self, PyObject *args, PyObject * return NULL; } - Py_INCREF(self); + Py_INCREF(self); /* necessary? */ setReasonPyRecord(prec, reason); @@ -213,6 +233,8 @@ static PyObject *pyRecord_asyncFinish(pyRecord *self, PyObject *args, PyObject * static PyMethodDef pyRecord_methods[] = { {"name", (PyCFunction)pyRecord_name, METH_NOARGS, "Return record name string"}, + {"isPyRecord", (PyCFunction)pyRecord_ispyrec, METH_NOARGS, + "Is this record using Python Device."}, {"info", (PyCFunction)pyRecord_info, METH_VARARGS, "Lookup info name\ninfo(name, def=None)"}, {"infos", (PyCFunction)pyRecord_infos, METH_NOARGS, diff --git a/devsupApp/src/pydevsup.h b/devsupApp/src/pydevsup.h index 6539d70..cdfbda2 100644 --- a/devsupApp/src/pydevsup.h +++ b/devsupApp/src/pydevsup.h @@ -11,6 +11,7 @@ int pyRecord_prepare(void); void pyRecord_setup(PyObject *module); int isPyRecord(dbCommon *); +int canIOScanRecord(dbCommon *); int setReasonPyRecord(dbCommon *, PyObject *); int clearReasonPyRecord(dbCommon *);