📄 dbbufferc.nc
字号:
case 1: //command buffer supports 1 integer (short) parameter if (cmd->params.params[0] != INT16 && cmd->params.params[0] != UINT16 && cmd->params.params[0] != INT8 && cmd->params.params[0] != UINT8) return err_UnknownError; params.numParams = 1; params.paramDataPtr[0] = &cmdStr[1]; //2nd and 3rd bytes are command param break; default: return err_InvalidIndex; } call CommandUse.invoke(cmd->name, result, &schema_err, ¶ms); } } break; case kEEPROM: if (mState != kIDLE) { return err_ResultBufferBusy; } if (!buf->u.eeprom.isOpen) { return err_BufferNotOpen; } //must do this to increment row numbers, etc. err = calcNextFreeRow(buf); if (err != err_NoError) { return err; } mState = kEEPROM_ALLOC_ROW; mCurResult = r; mCurBuffer = bufferId; *pending = TRUE; mCurRowHandle = mEepromRow; if (mEepromRow == NULL) { //+ 1 since we need an extra byte for the length if (call MemAlloc.allocate(&mEepromRow, call QueryResultIntf.resultSize(r, pq) + 1) != SUCCESS) { *pending = FALSE; mState = kIDLE; cleanupBuffer(bufferId, __LINE__); return err_EepromFailure; } } else { //+ 1 since we need an extra byte for the length if (call MemAlloc.reallocate(mEepromRow, call QueryResultIntf.resultSize(r, pq) + 1) != SUCCESS) { *pending = FALSE; mState = kIDLE; cleanupBuffer(bufferId, __LINE__); return err_EepromFailure; } } break; case kRAM: if (mState != kIDLE) { return err_ResultBufferBusy; } mState = kALLOC_ROW; row = buf->nextFree; err = calcNextFreeRow(buf); if (err != err_NoError) { mState = kIDLE; return err; } //need to allocate the buffer for this row mCurResult = r; mCurRow = row; mCurBuffer = bufferId; *pending = TRUE; bufList = (Handle *)(*buf->u.bufdata); if (bufList[row] != NULL) { //realloc'ing can be much more efficient than allocing all over again, //especially if the results are the same size (which should be the common case) mCurRowHandle = bufList[row]; if (call MemAlloc.reallocate(bufList[row], call QueryResultIntf.resultSize(r, pq)) != SUCCESS) { *pending = FALSE; mState = kIDLE; cleanupBuffer(bufferId, __LINE__); return err_OutOfMemory; } } else { if (call MemAlloc.allocate(&mCurRowHandle, call QueryResultIntf.resultSize(r, pq)) != SUCCESS) { *pending = FALSE; mState = kIDLE; cleanupBuffer(bufferId, __LINE__); return err_OutOfMemory; } } break; default: return err_UnknownError; } return err_NoError; } /* Given a query results in mCurResult, a query in mCurQuery, and a current result index in mCurResultIdx, send the next result out (if there are more to be sent), or do nothing. The caller can determine if results are being sent by looking at the value of the mState flag on return -- if is "kIDLE", nothing is being done, otherwise, a result is being sent. */ TinyDBError continueRadioBufferEnqueue() { ParsedQuery *pq = mCurQuery; QueryResult *r = mCurResult; int numResults = call QueryResultIntf.numRecords(r, pq); QueryResult newqr; TinyDBError err = err_NoError; bool pending = FALSE; ResultTuple rtup; mState = kRADIO_ENQUEUE; if (mCurResultIdx >= numResults) { mState = kIDLE; return err_NoError; } rtup = call QueryResultIntf.getResultTuple(r, mCurResultIdx++, pq); if (rtup.error != err_NoError) { mState = kIDLE; return rtup.error; } err = call QueryResultIntf.fromResultTuple(rtup, &newqr, pq); if (err != err_NoError) { mState = kIDLE; return err; } err = call RadioQueue.enqueue((QueryResultPtr)&newqr, &pending); if (err != err_NoError) mState = kIDLE; if (pending) return err; else { if (err != err_NoError) { return err; } else return continueRadioBufferEnqueue(); //try to send the next result, if there is one } } /* Remove the first element from the db buffer & deallocate it (don't return it.) Use peek() to retrieve the first element without deallocating, then call pop() when finished (because peek returns a pointer into the buffer.) */ /* 1/23/02 SRM DBBuffer.pop is no longer supported! command TinyDBError DBBuffer.pop(uint8_t bufferId) { Buffer *buf; Handle data; uint16_t row; Handle *bufList; TinyDBError err = err_NoError; err = getBuf(bufferId, &buf); if (err != err_NoError) return err; if (buf->nextFull == buf->nextFree) return err_NoMoreResults; row = buf->nextFull; bufList = (Handle *)(*buf->u.bufdata); data = bufList[row]; if (data != NULL) { call MemAlloc.free(data); bufList[row] = NULL; } buf->nextFull++; if (buf->nextFull >= buf->numRows) buf->nextFull = 0; return err; } */ /** Copy the top most result in the buffer into buf @return err_NoMoreResults if no results are available @return err_UnsupportedBuffer if the buffer doesn't support peek/pop */ command TinyDBError DBBuffer.peek(uint8_t bufferId, QueryResult *qr, bool *pending) { Buffer *buf; TinyDBError err; uint16_t row; Handle *bufList; if (bufferId == kRADIO || bufferId == kATTR_BUF || bufferId == kCOMMAND_BUF || bufferId == kEVENT_BUF || bufferId == kQUERY_BUF) return err_UnsupportedBuffer; if (mState != kIDLE) { return err_ResultBufferBusy; } mState = kREAD_ROW; *pending = FALSE; //DEBUG("peek", 4); err = getBuf(bufferId, &buf); if (err != err_NoError) { mState = kIDLE; goto done; } switch(buf->type) { case kRAM: row= buf->nextFull; if (row == buf->nextFree && buf->numRows != 1) { //special case single row... err = err_NoMoreResults; mState = kIDLE; goto done; } bufList = (Handle *)(*buf->u.bufdata); if (bufList[row] == NULL) { err = err_NoMoreResults; mState = kIDLE; goto done; } call QueryResultIntf.fromBytes((QueryResultPtr)*bufList[row], qr, *buf->qh); //memcpy(qr, &(*buf->u.bufdata)[row*buf->rowSize],buf->rowSize); mState = kIDLE; break; case kEEPROM:#ifdef kMATCHBOX mCurBuffer = bufferId; mCurResult = qr; *pending = TRUE; if (!buf->u.eeprom.isOpen) { if (call FileRead.open(*buf->name) == FAIL) { err = err_EepromFailure; *pending = FALSE; mState = kIDLE; } } else { if (buf->u.eeprom.isWrite) { //we can't read if it's open for writing *pending = FALSE; mState = kIDLE; err = err_BufferOpenForWriting; } else { post readEEPROMRow(); } }#else err = err_EepromFailure; *pending = FALSE; mState = kIDLE;#endif break; default: err = err_UnknownError; mState = kIDLE; } done: //mState = kIDLE; return err; }#ifdef kMATCHBOX /** Task to read a row from the EEPROM into mCurResult, assuming mCurBuffer contains the ID of the buffer to be read from and ReadFile is currently open to the file associated with the buffer. */ task void readEEPROMRow() { Buffer *buf; TinyDBError err; err = getBuf(mCurBuffer, &buf); if (err != err_NoError) { mState = kIDLE; signal DBBuffer.getComplete(mCurBuffer, mCurResult, err_UnsupportedBuffer); } switch (mState) { case kREAD_ROW: mState = kREADING_LENGTH; buf->u.eeprom.isWrite = FALSE; buf->u.eeprom.isOpen = TRUE; if (call FileRead.read(&mLen, 1) == FAIL) { mState = kIDLE; signal DBBuffer.getComplete(mCurBuffer, mCurResult, err_EepromFailure); } break; case kREADING_LENGTH: mState = kALLOC_FOR_READ; mCurRowHandle = mEepromRow; if (mEepromRow == NULL) { if (call MemAlloc.allocate(&mEepromRow, mLen) != SUCCESS) { mState = kIDLE; signal DBBuffer.getComplete(mCurBuffer, mCurResult, err_OutOfMemory); } } else { if (call MemAlloc.reallocate(mEepromRow, mLen) != SUCCESS) { mState = kIDLE; signal DBBuffer.getComplete(mCurBuffer, mCurResult, err_OutOfMemory); } } break; case kALLOC_FOR_READ: mState = kREADING_DATA; call MemAlloc.lock(mEepromRow); if (call FileRead.read(*mEepromRow, mLen) == FAIL) { mState = kIDLE; signal DBBuffer.getComplete(mCurBuffer, mCurResult, err_EepromFailure); } break; case kREADING_DATA: //HACK! -- this is fucked up -- query result now may have pointers into mEepromRow, which //will only be valid until the next call to read or write call QueryResultIntf.fromBytes((QueryResultPtr)*mEepromRow, mCurResult, *buf->qh); //unlocking here is a BAD THING -- handle may move, result may become invalid // if it has pointers into mEeprom row, which will only be the case for // certain aggregate queries. call MemAlloc.unlock(mEepromRow); { TuplePtr t; char numStr[5]; int i; call QueryResultIntf.toTuplePtr(mCurResult, *buf->qh, &t); itoa((*buf->qh)->numFields, numStr, 10); mDbgBuf[0] = 0; strcat(mDbgBuf, numStr); strcat(mDbgBuf, ","); for(i=0;i<(*buf->qh)->numFields;i++) { itoa(*(uint16_t *)(call TupleIntf.getFieldPtr(*buf->qh, t, i)), numStr, 10); if (strlen(mDbgBuf) + strlen(numStr) + 1< sizeof(mDbgBuf)) { strcat(mDbgBuf, numStr); strcat(mDbgBuf, ","); } } DEBUG(mDbgBuf, strlen(mDbgBuf)); } mState = kIDLE; signal DBBuffer.getComplete(mCurBuffer, mCurResult, err_NoError); break; default: return; } }#endif /** Copy the nth result in the buffer into buf @return err_NoMoreResults if idx > getSize() or if buffer[idx] is empty (unset) */ command TinyDBError DBBuffer.getResult(uint8_t bufferId, uint16_t idx, QueryResult *qr, bool *pending) { TinyDBError err = err_NoError; if (mState != kIDLE) { return err_ResultBufferBusy; } mState = kREAD_ROW; switch (bufferId) { //is this a special case buffer case kATTR_BUF: { TuplePtr t; char *field; if (idx >= call AttrUse.numAttrs()) { err = err_NoMoreResults; goto done; } //the tuple part of the query result t = &qr->d.t; t->notNull = 0; t->numFields = NUM_ATTR_FIELDS; //HACK -- hard code the retrieval of catalog fields // FIELD 1 : Name field = call TupleIntf.getFieldPtrNoQuery(t, 0, NUM_ATTR_FIELDS, ATTR_SIZES, ATTR_TYPES); if (field != NULL) { AttrDescPtr adp = call AttrUse.getAttrById(idx); call TupleIntf.setFieldNoQuery(t,0,NUM_ATTR_FIELDS, ATTR_SIZES, ATTR_TYPES, adp->name); } break; } default: { Buffer *buf; uint16_t size; uint16_t row; Handle *bufList; err = getBuf(bufferId, &buf); *pending = FALSE; if (err != err_NoError) goto done; if (buf->nextFull == buf->nextFree && buf->numRows != 1) { err = err_NoMoreResults; goto done; } call DBBuffer.size(bufferId, &size); if (idx >= size) { err = err_NoMoreResults; goto done; } //see comment at beginning of document for info on slot management & indexing if (buf->nextFull > buf->nextFree) { if (idx >= (buf->numRows - buf->nextFull)) { row = idx - (buf->numRows - buf->nextFull); } else row = buf->nextFull + idx; } else { row = buf->nextFull + idx; } switch (buf->type) { case kRAM: bufList = (Handle *)(*buf->u.bufdata); call QueryResultIntf.fromBytes((QueryResultPtr)*bufList[row], qr, *buf->qh); //memcpy(qr, &(*buf->u.bufdata)[row*buf->rowSize], buf->rowSize); break; default: err = err_UnknownError; } } } done: mState = kIDLE; return err; } /* Return the number of used rows in the buffer */ command TinyDBError DBBuffer.size(uint8_t bufferId, uint16_t *size) { Buffer *buf; TinyDBError err = err_NoError; switch (bufferId) { case kATTR_BUF: *size = call AttrUse.numAttrs(); return err_NoError; default: err = getBuf(bufferId, &buf); if (err != err_NoError) return err;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -