Пример #1
0
/*
 * 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);
}
Пример #2
0
/*
 * 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);
}
Пример #3
0
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);
}    
Пример #4
0
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;
}
Пример #5
0
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);
}
Пример #6
0
    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;
Пример #7
0
/*
 * 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;
}
Пример #8
0
/*
 * 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;
}