/* * Get value from a queued PV. */ epicsShareFunc boolean seq_pvGetQ(SS_ID ss, CH_ID chId) { PROG *sp = ss->prog; CHAN *ch = sp->chan + chId; void *var = valPtr(ch,ss); EF_ID ev_flag = ch->syncedTo; PVMETA *meta = metaPtr(ch,ss); boolean was_empty; struct getq_cp_arg arg = {ch, var, meta}; if (!ch->queue) { errlogSevPrintf(errlogMajor, "pvGetQ(%s): user error (not queued)\n", ch->varName ); return FALSE; } was_empty = seqQueueGetF(ch->queue, getq_cp, &arg); if (ev_flag) { epicsMutexMustLock(sp->lock); /* If queue is now empty, clear the event flag */ if (seqQueueIsEmpty(ch->queue)) { bitClear(sp->evFlags, ev_flag); } epicsMutexUnlock(sp->lock); } return (!was_empty); }
/* * ss_read_buffer_static() - static version of ss_read_buffer. * This is to enable inlining in the for loop in ss_read_all_buffer. */ static void ss_read_buffer_static(SSCB *ss, CHAN *ch, boolean dirty_only) { char *val = valPtr(ch,ss); char *buf = bufPtr(ch); ptrdiff_t nch = chNum(ch); /* Must take dbCount for db channels, else we overwrite elements we didn't get */ size_t count = ch->dbch ? ch->dbch->dbCount : ch->count; size_t var_size = ch->type->size * count; if (!ss->dirty[nch] && dirty_only) return; epicsMutexMustLock(ch->varLock); DEBUG("ss %s: before read %s", ss->ssName, ch->varName); print_channel_value(DEBUG, ch, val); memcpy(val, buf, var_size); if (ch->dbch) { /* structure copy */ ss->metaData[nch] = ch->dbch->metaData; } DEBUG("ss %s: after read %s", ss->ssName, ch->varName); print_channel_value(DEBUG, ch, val); ss->dirty[nch] = FALSE; epicsMutexUnlock(ch->varLock); }
JSONSerializer::valPtr JSONSerializer::parse (const std::string &in) { Json::Value *root = new Json::Value(); Json::Reader reader; if (!reader.parse(in, *root)) { // report to the user the failure and their locations in the document. std::cout << "Failed to parse message\n" << reader.getFormattedErrorMessages() << " : " << in << std::endl; exit(1); } return valPtr(root); }
string XJson::encode(const ::urbi::UValue& data) { if (data.type != ::urbi::DATA_DICTIONARY && data.type != ::urbi::DATA_LIST) { send("throw \"Only UList or UDictionary are supported by UJson.\";"); return ""; } Document doc; StringBuffer stream; Writer<StringBuffer> writer(stream); unique_ptr<Value> valPtr(fromUValue(data, doc.GetAllocator())); (*valPtr).Accept(writer); string result(stream.GetString()); stream.Clear(); return result; }
static void anonymous_put(SS_ID ss, CHAN *ch) { char *var = valPtr(ch,ss); if (ch->queue) { QUEUE queue = ch->queue; pvType type = ch->type->getType; /*BUG? should that be putType?*/ size_t size = ch->type->size; boolean full; struct putq_cp_arg arg = {ch, var}; DEBUG("anonymous_put: type=%d, size=%d, count=%d, buf_size=%d, q=%p\n", type, size, ch->count, pv_size_n(type, ch->count), queue); print_channel_value(DEBUG, ch, var); /* Note: Must lock here because multiple state sets can issue pvPut calls concurrently. OTOH, no need to lock against CA callbacks, because anonymous and named PVs are disjoint. */ epicsMutexMustLock(ch->varLock); full = seqQueuePutF(queue, putq_cp, &arg); if (full) { errlogSevPrintf(errlogMinor, "pvPut on queued channel '%s' (anonymous): " "last queue element overwritten (queue is full)\n", ch->varName ); } epicsMutexUnlock(ch->varLock); } else { /* Set dirty flag only if monitored */ ss_write_buffer(ch, var, 0, ch->monitored); } /* If there's an event flag associated with this channel, set it */ if (ch->syncedTo) seq_efSet(ss, ch->syncedTo); /* Wake up each state set that uses this channel in an event */ ss_wakeup(ss->prog, ch->eventNum); }
if ( !(g = allocString((len+1)*sizeof(pl_wchar_t) PASS_LD)) ) return 0; t = (char *)&g[1]; w = (pl_wchar_t*)t; w[0] = 0; *t = 'W'; memcpy(&w[1], s, len*sizeof(pl_wchar_t)); } return consPtr(g, TAG_STRING|STG_GLOBAL); } char * getCharsString__LD(word w, size_t *len ARG_LD) { Word p = valPtr(w); word m = *p; size_t wn = wsizeofInd(m); size_t pad = padHdr(m); char *s; if ( len ) *len = wn*sizeof(word) - pad - 1; /* -1 for the 'B' */ s = (char *)&p[1]; if ( *s == 'B' ) return s+1; assert(*s == 'W'); return NULL;
/* * Put a variable's value to a PV, with timeout. */ epicsShareFunc pvStat seq_pvPutTmo(SS_ID ss, CH_ID chId, enum compType compType, double tmo) { PROG *sp = ss->prog; CHAN *ch = sp->chan + chId; pvStat status; unsigned count; char *var = valPtr(ch,ss); /* ptr to value */ PVREQ *req; DBCHAN *dbch = ch->dbch; PVMETA *meta = metaPtr(ch,ss); DEBUG("pvPut: pv name=%s, var=%p\n", dbch ? dbch->dbName : "<anonymous>", var); /* First handle anonymous PV (safe mode only) */ if (optTest(sp, OPT_SAFE) && !dbch) { anonymous_put(ss, ch); return pvStatOK; } if (!dbch) { errlogSevPrintf(errlogMajor, "pvPut(%s): user error (not assigned to a PV)\n", ch->varName ); return pvStatERROR; } /* Check for channel connected */ status = check_connected(dbch, meta); if (status != pvStatOK) return status; /* Determine whether to perform synchronous, asynchronous, or plain put ((+a) option was never honored for put, so DEFAULT means fire-and-forget) */ status = check_pending(pvEventPut, ss, ss->putReq + chId, ch->varName, dbch, meta, compType, tmo); if (status != pvStatOK) return status; /* Determine number of elements to put (don't try to put more than db count) */ count = dbch->dbCount; /* Perform the PV put operation (either non-blocking or with a callback routine specified) */ if (compType == DEFAULT) { status = pvVarPutNoBlock( &dbch->pvid, /* PV id */ ch->type->putType, /* data type */ count, /* element count */ (pvValue *)var); /* data value */ if (status != pvStatOK) { pv_call_failure(dbch, meta, status); errlogSevPrintf(errlogFatal, "pvPut(var %s, pv %s): pvVarPutNoBlock() failure: %s\n", ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid)); return status; } } else { /* Allocate and initialize a pv request */ req = (PVREQ *)freeListMalloc(sp->pvReqPool); req->ss = ss; req->ch = ch; assert(ss->putReq[chId] == NULL); ss->putReq[chId] = req; status = pvVarPutCallback( &dbch->pvid, /* PV id */ ch->type->putType, /* data type */ count, /* element count */ (pvValue *)var, /* data value */ req); /* user arg */ if (status != pvStatOK) { pv_call_failure(dbch, meta, status); errlogSevPrintf(errlogFatal, "pvPut(var %s, pv %s): pvVarPutCallback() failure: %s\n", ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid)); ss->putReq[chId] = NULL; /* cancel the request */ freeListFree(sp->pvReqPool, req); check_connected(dbch, meta); return status; } if (compType == SYNC) /* wait for completion */ { pvSysFlush(sp->pvSys); status = wait_complete(pvEventPut, ss, ss->putReq + chId, dbch, meta, tmo); if (status != pvStatOK) return status; } } return pvStatOK; }
/* * Put a variable's value to a PV. */ epicsShareFunc pvStat epicsShareAPI seq_pvPut(SS_ID ss, VAR_ID varId, enum compType compType) { SPROG *sp = ss->sprog; CHAN *ch = sp->chan + varId; pvStat status; unsigned count; char *var = valPtr(ch,ss); /* ptr to value */ PVREQ *req; DBCHAN *dbch = ch->dbch; PVMETA *meta = metaPtr(ch,ss); epicsEventId putSem = ss->putSemId[varId]; double tmo = seq_sync_timeout; DEBUG("pvPut: pv name=%s, var=%p\n", dbch ? dbch->dbName : "<anonymous>", var); /* First handle anonymous PV (safe mode only) */ if ((sp->options & OPT_SAFE) && !dbch) { anonymous_put(ss, ch); return pvStatOK; } if (!dbch) { errlogSevPrintf(errlogMajor, "pvPut(%s): user error (variable not assigned)\n", ch->varName ); return pvStatERROR; } /* Check for channel connected */ status = check_connected(dbch, meta); if (status) return status; /* Determine whether to perform synchronous, asynchronous, or plain put ((+a) option was never honored for put, so DEFAULT means non-blocking and therefore implicitly asynchronous) */ if (compType == SYNC) { double before, after; pvTimeGetCurrentDouble(&before); switch (epicsEventWaitWithTimeout(putSem, tmo)) { case epicsEventWaitOK: pvTimeGetCurrentDouble(&after); tmo -= (after - before); break; case epicsEventWaitTimeout: errlogSevPrintf(errlogMajor, "pvPut(ss %s, var %s, pv %s): failed (timeout " "waiting for other put requests to finish)\n", ss->ssName, ch->varName, dbch->dbName ); return pvStatERROR; case epicsEventWaitError: /* try to recover */ ss->putReq[varId] = NULL; epicsEventSignal(putSem); errlogSevPrintf(errlogFatal, "pvPut: epicsEventWaitWithTimeout() failure\n"); return pvStatERROR; } } else if (compType == ASYNC) { switch (epicsEventTryWait(putSem)) { case epicsEventWaitOK: if (ss->putReq[varId] != NULL) { /* previous request timed out but user did not call pvPutComplete */ ss->putReq[varId] = NULL; } break; case epicsEventWaitTimeout: meta->status = pvStatERROR; meta->severity = pvSevrMAJOR; meta->message = "already one put pending"; status = meta->status; errlogSevPrintf(errlogMajor, "pvPut(ss %s, var %s, pv %s): user error " "(there is already a put pending for this variable/" "state set combination)\n", ss->ssName, ch->varName, dbch->dbName ); return pvStatERROR; case epicsEventWaitError: /* try to recover */ ss->putReq[varId] = NULL; epicsEventSignal(putSem); errlogSevPrintf(errlogFatal, "pvPut: epicsEventTryWait() failure\n"); return pvStatERROR; } } /* Determine number of elements to put (don't try to put more than db count) */ count = dbch->dbCount; /* Perform the PV put operation (either non-blocking or with a callback routine specified) */ if (compType == DEFAULT) { status = pvVarPutNoBlock( dbch->pvid, /* PV id */ ch->type->putType, /* data type */ count, /* element count */ (pvValue *)var); /* data value */ if (status != pvStatOK) { errlogSevPrintf(errlogFatal, "pvPut(var %s, pv %s): pvVarPutNoBlock() failure: %s\n", ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid)); return status; } } else { /* Allocate and initialize a pv request */ req = (PVREQ *)freeListMalloc(sp->pvReqPool); req->ss = ss; req->ch = ch; assert(ss->putReq[varId] == NULL); ss->putReq[varId] = req; status = pvVarPutCallback( dbch->pvid, /* PV id */ ch->type->putType, /* data type */ count, /* element count */ (pvValue *)var, /* data value */ seq_put_handler, /* callback handler */ req); /* user arg */ if (status != pvStatOK) { ss->putReq[varId] = NULL; errlogSevPrintf(errlogFatal, "pvPut(var %s, pv %s): pvVarPutCallback() failure: %s\n", ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid)); freeListFree(sp->pvReqPool, req); epicsEventSignal(putSem); check_connected(dbch, meta); return status; } } /* Synchronous: wait for completion (10s timeout) */ if (compType == SYNC) { epicsEventWaitStatus event_status; pvSysFlush(sp->pvSys); event_status = epicsEventWaitWithTimeout(putSem, tmo); ss->putReq[varId] = NULL; epicsEventSignal(putSem); switch (event_status) { case epicsEventWaitOK: status = check_connected(dbch, meta); if (status) return status; break; case epicsEventWaitTimeout: meta->status = pvStatTIMEOUT; meta->severity = pvSevrMAJOR; meta->message = "put completion timeout"; return meta->status; break; case epicsEventWaitError: meta->status = pvStatERROR; meta->severity = pvSevrMAJOR; meta->message = "put completion failure"; return meta->status; break; } } return pvStatOK; }