📄 wvlib.c
字号:
* also part of the BUFFER_ID, as a general purpose mechanism for telling* users of the buffer when threshold bytes of data are contained in the* buffer. This gives the the uploader a way of controlling the frequency * and size of uploads. The threshold is assigned by the buffer mechanism,* but can be an arbitrary value. In general, the buffer may assign threshold* to meet a buffer contraint, or it may allow the user to assign it, and * allow access to its value in the structure pointed to by the BUFFER_ID.** All buffer accesses are protected with interrupts locked out.** RETURNS: OK when buffer is successfully emptied and uploaded and* the upload task ID's exitWhenEmpty is set to TRUE.* ERROR if an error occurs with the upload path or buffers; event* logging is stopped if an error occurs.** SEE ALSO:* NOMANUAL**/static STATUS wvUpload ( WV_UPLOADTASK_ID upTaskId /* this task's descriptor */ ) { int nReserved; /* num bytes reserved and possible to upload */ int nToWrite; /* num bytes that should be written to host */ int nUploaded; /* number of bytes actually written to host */ int nToCommit; /* number of bytes to commit in the buffer */ int tmp; /* temporary used to count uploaded bytes */ BOOL bufferEmpty; /* used to exit when buffer is empty */ UINT8 *pData; /* pointer to the read-reserved data */ int lockKey; /* for interrupt locking */ BUFFER_ID bufId; /* convenient access to upTaskId->bufferId */ UPLOAD_ID pathId; /* same for upTaskId->uploadPathId */ /* Check that the upload-task id has appropriate information. */ if (upTaskId == NULL) return (ERROR); if (upTaskId->bufferId == NULL) { upTaskId->status = ERROR; return (ERROR); } if (upTaskId->uploadPathId == NULL) { upTaskId->status = ERROR; return (ERROR); } /* Initialize variables. */ bufId = upTaskId->bufferId; pathId = upTaskId->uploadPathId; bufferEmpty = FALSE; nToWrite = 0; while (TRUE) { /* * Initialize variables that allow us to stop uploading at the right * time. Assuming that there is data in the buffer (bufferEmtpy = * FALSE) is alright because nothing below will error if there is * not. In other words, bufferEmpty accurately describes when the * buffer is empty but does not accurately describe when the buffer * is not empty. */ nUploaded = 0; bufferEmpty = FALSE; /* * If the caller requested to exit when the buffer is empty, give * him/er the result immediately, even if there is no data available. * Also, if there is still more than a threshold of data in the buffer, * continue uploading. Otherwise block until sufficient data becomes * available. */ lockKey = intLock (); tmp = bufId->nBytesRtn (bufId); intUnlock (lockKey); if (! upTaskId->exitWhenEmpty && (tmp < bufId->threshold)) semTake (& bufId->threshXSem, WAIT_FOREVER); /* * Upload in chunks of size bufId->threshold. The readReserve * routine of the buffer only guarantees that every time the * threshXSem is able to be taken there are threshold bytes of data * in the buffer. That data may not be contiguous, and so we have * to loop until threshold bytes have been uploaded. */ while ((nUploaded < bufId->threshold) && !bufferEmpty) { /* Reserve as many contiguous bytes as possible from the buffer. */ lockKey = intLock (); nReserved = bufId->readReserveRtn (bufId, &pData); intUnlock (lockKey); if (nReserved == ERROR) { /* * If an error occurs close the upload path and stop event * logging. There is no harm in turning event logging off * if it is not currently on. */ lockKey = intLock (); wvEvtLogStop(); intUnlock (lockKey); pathId->errorRtn (pathId); upTaskId->status = ERROR; logMsg ("tWvUpload: failed to read from buffer.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } /* Notice when the buffer is emptied. */ if (nReserved == 0) bufferEmpty = TRUE; else bufferEmpty = FALSE; /* * Write as many bytes as possible that still need to be uploaed, * to the host, but not more than threshold. And, remember how * many to commit later. */ nToWrite = (nReserved > (bufId->threshold - nUploaded)) ? (bufId->threshold - nUploaded) : nReserved; nToCommit = nToWrite; if (uploadPathWrite (pathId, pData, nToWrite) == ERROR) { /* * There is still no harm in turning off event logging * if it is not currently on. */ lockKey = intLock (); wvEvtLogStop(); intUnlock (lockKey); pathId->errorRtn (pathId); upTaskId->status = ERROR; logMsg ("tWVUpload: failed writing to host.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } /* * At this point all the reserved bytes that were possible to * read in this pass through the loop have been uploaded. Those * bytes are committed before determining whether to loop again. */ lockKey = intLock (); tmp = bufId->readCommitRtn (bufId, nToCommit); intUnlock (lockKey); if (tmp == ERROR) { /* * There is no harm in turning logging off if it is already * off. */ lockKey = intLock (); wvEvtLogStop(); intUnlock (lockKey); pathId->errorRtn (pathId); upTaskId->status = ERROR; logMsg ("tWvUpload: failed to commit uploaded bytes.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } nUploaded += nToCommit; } /* * At this point the buffer is empty or threshold bytes have been * uploaded. Exit only if the buffer was emptied and the user * requested not to wait for more data. */ if (upTaskId->exitWhenEmpty && bufferEmpty) { upTaskId->status = OK; semGive (& upTaskId->uploadCompleteSem); return (OK); } } }/********************************************************************************* wvUploadStart - start upload of events to the host (WindView)** This routine starts uploading events from the event buffer to the host.* Events can be uploaded either continuously or in one pass until the* buffer is emptied. If <uploadContinuously> is set to TRUE, the task* uploading events pends until more data arrives in the buffer. If FALSE,* the buffer is flushed without waiting, but this routine * returns immediately with an ID that can be used to kill the upload task.* Upload is done by spawning the task 'tWVUpload'. The buffer to upload is * identified by <bufId>, and the upload path to use is identified by <pathId>.** This routine blocks if no event data is in the buffer, so it should* be called before event logging is started to ensure the buffer does* not overflow.** RETURNS: A valid WV_UPLOADTASK_ID if started for continuous* upload, a non-NULL value if started for one-pass upload, and NULL * if the task can not be spawned or memory for the descriptor * can not be allocated.**/WV_UPLOADTASK_ID wvUploadStart ( BUFFER_ID bufId, /* event data buffer ID */ UPLOAD_ID pathId, /* upload path to host */ BOOL uploadContinuously /* upload continuously if true */ ) { WV_UPLOADTASK_ID upTaskId; /* returned to later identify the upload task */ /* Check for valid parameters. */ if (bufId == NULL || pathId == NULL) return (NULL); /* * Create and initialize the upload task descriptor to return to the * user. This id is necessary for stopping the task later. */ if ((upTaskId = (WV_UPLOADTASK_ID) malloc (sizeof (WV_UPLOADTASK_DESC))) == NULL) { logMsg ("wvUploadStart: can't alloc uploadTask id memory.\n", 0,0,0,0,0,0); return (NULL); } if (semBInit (& upTaskId->uploadCompleteSem, SEM_Q_PRIORITY, SEM_EMPTY) == ERROR) { logMsg ("wvUploadStart: can't init uploadTask sem.\n",0,0,0,0,0,0); return (NULL); } upTaskId->bufferId = bufId; upTaskId->uploadPathId = pathId; upTaskId->status = OK; if (uploadContinuously) upTaskId->exitWhenEmpty = FALSE; else upTaskId->exitWhenEmpty = TRUE; /* Now spawn the task. */ if ((upTaskId->uploadTaskId = taskSpawn ("tWVUpload", wvUploadTaskPriority, wvUploadTaskOptions, wvUploadTaskStackSize, wvUpload, (int) upTaskId, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR) { logMsg ("wvUploadStart: can't spawn uploadTask.\n",0,0,0,0,0,0); return (NULL); } return (upTaskId); }/********************************************************************************* wvUploadStop - stop upload of events to host (WindView)** This routine stops continuous upload of events to the host. It does this* by making a request to the upload task to terminate after it has emptied* the buffer. For this reason it is important to make sure data is no* longer being logged to the buffer before calling this routine.* * This task blocks until the buffer is emptied, and then frees memory* associated with <upTaskId>.** RETURNS: OK if the upload task terminates successfully, * or ERROR either if <upTaskId> is invalid or if the upload task terminates* with an ERROR.**/STATUS wvUploadStop ( WV_UPLOADTASK_ID upTaskId ) { STATUS retStatus; if (upTaskId == NULL) return (ERROR); /* * Ask the upload task to flush the buffer and then exit. The upload * task may have emptied the buffer and be waiting on the buffer's * threshold-crossed semaphore, so we give that semaphore so the task * won't pend forever. */ upTaskId->exitWhenEmpty = TRUE; semGive (& upTaskId->bufferId->threshXSem); /* Wait for flushing to complete, but only if uploader worked correctly */ if (upTaskId->status == OK) semTake (& upTaskId->uploadCompleteSem, WAIT_FOREVER); /* Free up the memory associated with the upload descriptor. */ semTerminate (& upTaskId->uploadCompleteSem); retStatus = upTaskId->status; free (upTaskId); return (retStatus); }/********************************************************************************* wvUploadTaskConfig - set priority and stacksize of 'tWVUpload' task (WindView)** This routine sets the stack size and priority of future instances of * the event-data upload task, created by calling wvUploadStart(). The default* stack size for this task is 5000 bytes, and the default priority is 150.* * RETURNS: N/A*/void wvUploadTaskConfig ( int stackSize, /* the new stack size for tWVUpload */ int priority /* the new priority for tWVUpload */ ) { wvUploadTaskStackSize = stackSize; wvUploadTaskPriority = priority; }/********************************************************************************* wvLogHeaderCreate - create the event-log header (WindView)** This routine creates the header of EVENT_CONFIG, EVENT_BUFFER, and EVENT_BEGIN* events that is required at the beginning of every event log. These events are* stored in a packed array allocated from the specified memory partition.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -