TRI_fulltext_list_t* TRI_IntersectListFulltextIndex (TRI_fulltext_list_t* lhs, TRI_fulltext_list_t* rhs) { TRI_fulltext_list_t* list; TRI_fulltext_list_entry_t last; TRI_fulltext_list_entry_t* lhsEntries; TRI_fulltext_list_entry_t* rhsEntries; TRI_fulltext_list_entry_t* listEntries; uint32_t l, r; uint32_t numLhs, numRhs; uint32_t listPos; // check if one of the pointers is NULL if (lhs == NULL) { return rhs; } if (rhs == NULL) { return lhs; } numLhs = GetNumEntries(lhs); numRhs = GetNumEntries(rhs); // printf("list intersection lhs: %lu rhs: %lu\n\n", (unsigned long) numLhs, (unsigned long) numRhs); // check the easy cases when one of the lists is empty if (numLhs == 0 || numRhs == 0) { if (lhs != NULL) { TRI_FreeListFulltextIndex(lhs); } if (rhs != NULL) { TRI_FreeListFulltextIndex(rhs); } return TRI_CreateListFulltextIndex(0); } // we have at least one entry in each list list = TRI_CreateListFulltextIndex(numLhs < numRhs ? numLhs : numRhs); if (list == NULL) { TRI_FreeListFulltextIndex(lhs); TRI_FreeListFulltextIndex(rhs); return NULL; } SortList(lhs); lhsEntries = GetStart(lhs); l = 0; SortList(rhs); rhsEntries = GetStart(rhs); r = 0; listPos = 0; listEntries = GetStart(list); last = 0; while (true) { while (l < numLhs && lhsEntries[l] <= last) { ++l; } while (r < numRhs && rhsEntries[r] <= last) { ++r; } again: if (l >= numLhs || r >= numRhs) { break; } if (lhsEntries[l] < rhsEntries[r]) { ++l; goto again; } else if (lhsEntries[l] > rhsEntries[r]) { ++r; goto again; } // match listEntries[listPos++] = last = lhsEntries[l]; ++l; ++r; } SetNumEntries(list, listPos); SetIsSorted(list, true); TRI_FreeListFulltextIndex(lhs); TRI_FreeListFulltextIndex(rhs); // printf("result list has %lu\n\n", (unsigned long) listPos); return list; }
TRI_fulltext_list_t* TRI_InsertListFulltextIndex (TRI_fulltext_list_t* list, const TRI_fulltext_list_entry_t entry) { TRI_fulltext_list_entry_t* listEntries; uint32_t numAllocated; uint32_t numEntries; bool unsort; numAllocated = GetNumAllocated(list); numEntries = GetNumEntries(list); listEntries = GetStart(list); unsort = false; if (numEntries > 0) { TRI_fulltext_list_entry_t lastEntry; // check whether the entry is already contained in the list lastEntry = listEntries[numEntries - 1]; if (entry == lastEntry) { // entry is already contained. no need to insert the same value again return list; } if (entry < lastEntry) { // we're adding at the end. we must update the sorted property if // the list is not sorted anymore unsort = true; } } if (numEntries + 1 >= numAllocated) { // must allocate more memory TRI_fulltext_list_t* clone; uint32_t newSize; newSize = (uint32_t) (numEntries * GROWTH_FACTOR); if (newSize == numEntries) { // 0 * something might not be enough... newSize = numEntries + 1; } // increase the existing list clone = IncreaseList(list, newSize); if (clone == NULL) { return NULL; } // switch over if (list != clone) { list = clone; listEntries = GetStart(list); } } if (unsort) { SetIsSorted(list, false); } // insert at the end listEntries[numEntries] = entry; SetNumEntries(list, numEntries + 1); return list; }
TRI_fulltext_list_t* TRI_UnioniseListFulltextIndex (TRI_fulltext_list_t* lhs, TRI_fulltext_list_t* rhs) { TRI_fulltext_list_t* list; TRI_fulltext_list_entry_t last; TRI_fulltext_list_entry_t* lhsEntries; TRI_fulltext_list_entry_t* rhsEntries; TRI_fulltext_list_entry_t* listEntries; uint32_t l, r; uint32_t numLhs, numRhs; uint32_t listPos; if (lhs == NULL) { return rhs; } if (rhs == NULL) { return lhs; } numLhs = GetNumEntries(lhs); numRhs = GetNumEntries(rhs); // check the easy cases when one of the lists is empty if (numLhs == 0) { TRI_FreeListFulltextIndex(lhs); return rhs; } if (numRhs == 0) { TRI_FreeListFulltextIndex(rhs); return lhs; } list = TRI_CreateListFulltextIndex(numLhs + numRhs); if (list == NULL) { TRI_FreeListFulltextIndex(lhs); TRI_FreeListFulltextIndex(rhs); return NULL; } SortList(lhs); lhsEntries = GetStart(lhs); l = 0; SortList(rhs); rhsEntries = GetStart(rhs); r = 0; listPos = 0; listEntries = GetStart(list); last = 0; while (true) { while (l < numLhs && lhsEntries[l] <= last) { ++l; } while (r < numRhs && rhsEntries[r] <= last) { ++r; } if (l >= numLhs && r >= numRhs) { break; } if (l >= numLhs && r < numRhs) { listEntries[listPos++] = last = rhsEntries[r++]; } else if (l < numLhs && r >= numRhs) { listEntries[listPos++] = last = lhsEntries[l++]; } else if (lhsEntries[l] < rhsEntries[r]) { listEntries[listPos++] = last = lhsEntries[l++]; } else { listEntries[listPos++] = last = rhsEntries[r++]; } } SetNumEntries(list, listPos); SetIsSorted(list, true); TRI_FreeListFulltextIndex(lhs); TRI_FreeListFulltextIndex(rhs); return list; }
void SQ::Init(uint16_t qId, uint16_t entrySize, uint32_t numEntries, uint16_t cqId) { uint64_t work; mCqId = cqId; Queue::Init(qId, entrySize, numEntries); LOG_NRM("Create SQ: (id,cqid,entrySize,numEntries) = (%d,%d,%d,%d)", GetQId(), GetCqId(), GetEntrySize(), GetNumEntries()); LOG_NRM("Allocating contiguous SQ memory in dnvme"); if (numEntries < 2) { throw FrmwkEx(HERE, "Number elements breaches spec requirement"); } else if (gRegisters->Read(CTLSPC_CAP, work) == false) { throw FrmwkEx(HERE, "Unable to determine MQES"); } // Detect if doing something that looks suspicious/incorrect/illegal work &= CAP_MQES; work += 1; // convert to 1-based if (work < (uint64_t)numEntries) { LOG_WARN("Creating Q with %d entries, but DUT only allows %d", numEntries, (uint32_t)work); } if (GetIsAdmin()) { if (gCtrlrConfig->IsStateEnabled()) { // At best this will cause tnvme to seg fault or a kernel crash // The NVME spec states unpredictable outcomes will occur. throw FrmwkEx(HERE, "Creating an ASQ while ctrlr is enabled is a shall not"); } // We are creating a contiguous ASQ. ASQ's have a constant well known // element size and no setup is required for this type of Q. int ret; struct nvme_create_admn_q q; q.elements = GetNumEntries(); q.type = ADMIN_SQ; LOG_NRM("Init contig ASQ: (id, cqid, entrySize, numEntries) = " "(%d, %d, %d, %d)", GetQId(), GetCqId(), GetEntrySize(), GetNumEntries()); if ((ret = ioctl(mFd, NVME_IOCTL_CREATE_ADMN_Q, &q)) < 0) { throw FrmwkEx(HERE, "Q Creation failed by dnvme with error: 0x%02X", ret); } } else { // We are creating a contiguous IOSQ. struct nvme_prep_sq q; q.sq_id = GetQId(); q.cq_id = GetCqId(); q.elements = GetNumEntries(); q.contig = true; CreateIOSQ(q); } // Contiguous Q's are created in dnvme and must be mapped back to user space mContigBuf = KernelAPI::mmap(GetQSize(), GetQId(), KernelAPI::MMR_SQ); if (mContigBuf == NULL) throw FrmwkEx(HERE, "Unable to mmap contig memory to user space"); }
void SQ::Init(uint16_t qId, uint16_t entrySize, uint32_t numEntries, const SharedMemBufferPtr memBuffer, uint16_t cqId) { uint64_t work; mCqId = cqId; Queue::Init(qId, entrySize, numEntries); LOG_NRM("Create SQ: (id,cqid,entrySize,numEntries) = (%d,%d,%d,%d)", GetQId(), GetCqId(), GetEntrySize(), GetNumEntries()); LOG_NRM("Allocating discontiguous SQ memory in tnvme"); if (numEntries < 2) { throw FrmwkEx(HERE, "Number elements breaches spec requirement"); } else if (gRegisters->Read(CTLSPC_CAP, work) == false) { throw FrmwkEx(HERE, "Unable to determine MQES"); } // Detect if doing something that looks suspicious/incorrect/illegal work &= CAP_MQES; work += 1; // convert to 1-based if (work < (uint64_t)numEntries) { LOG_WARN("Creating Q with %d entries, but DUT only allows %d", numEntries, (uint32_t)work); } if (memBuffer == MemBuffer::NullMemBufferPtr) { throw FrmwkEx(HERE, "Passing an uninitialized SharedMemBufferPtr"); } else if (GetIsAdmin()) { // There are no appropriate methods for an NVME device to report ASC/ACQ // creation errors, thus since ASC/ASQ may only be contiguous then don't // allow these problems to be injected, at best they will only succeed // to seg fault the app or crash the kernel. throw FrmwkEx(HERE, "Illegal memory alignment will corrupt"); } else if (memBuffer->GetBufSize() < GetQSize()) { LOG_ERR("Q buffer memory ambiguous to passed size params"); throw FrmwkEx(HERE, "Mem buffer size = %d, Q size = %d", memBuffer->GetBufSize(), GetQSize()); } else if (memBuffer->GetAlignment() != sysconf(_SC_PAGESIZE)) { // Nonconformance to page alignment will seg fault the app or crash // the kernel. This state is not testable since no errors can be // reported by hdw, thus disallow this attempt. throw FrmwkEx(HERE, "Q content memory shall be page aligned"); } // Zero out the content memory so the P-bit correlates to a newly alloc'd Q. // Also assuming life time ownership of this object if it wasn't created // by the RsrcMngr. mDiscontigBuf = memBuffer; mDiscontigBuf->Zero(); // We are creating a discontiguous IOSQ struct nvme_prep_sq q; q.sq_id = GetQId(); q.cq_id = GetCqId(); q.elements = GetNumEntries(); q.contig = false; CreateIOSQ(q); }
/** * @return true if the log was loaded successfully. */ BOOL CTextLogFile::LoadEntries(void) { #ifdef _DEBUG DWORD dwStartTime = GetTickCount(); #endif BOOL bResult = FALSE; PCTSTR pszLogFileName = GetLogFileName(); HANDLE hFile = CreateFile(pszLogFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { DWORD dwFileSize = (DWORD)GetFileSize(hFile, NULL); if (dwFileSize == 0) { // ignore empty files CloseHandle(hFile); return TRUE; } DWORD dwBufferSize = min(dwFileSize, g_dwMaxBufferSize); PBYTE pFileBuffer = new BYTE[dwBufferSize]; if (pFileBuffer) { BYTE arrUTF8Preamble[sizeof(g_arrUTF8Preamble)]; DWORD dwWritten = 0; if (ReadFile(hFile, arrUTF8Preamble, sizeof(arrUTF8Preamble), &dwWritten, NULL) && dwWritten == sizeof(arrUTF8Preamble) && memcmp(arrUTF8Preamble, g_arrUTF8Preamble, sizeof(arrUTF8Preamble)) == 0) { bResult = TRUE; DWORD dwCurrentPos = 0, dwLineStart = 0; for (;;) { dwWritten = 0; DWORD dwFreeSize = dwBufferSize - dwCurrentPos; if (! ReadFile(hFile, pFileBuffer + dwCurrentPos, dwFreeSize, &dwWritten, NULL)) goto end; BOOL bEndOfFile = dwWritten < dwFreeSize; dwWritten += dwCurrentPos; dwCurrentPos = 0; if (dwWritten == 0) goto end; for (;;) { if (dwCurrentPos >= dwWritten && ! bEndOfFile) { if (dwLineStart > 0) { dwCurrentPos -= dwLineStart; MoveMemory(pFileBuffer, pFileBuffer + dwLineStart, dwCurrentPos); dwLineStart = 0; } else { dwBufferSize *= 2; PBYTE pNewFileBuffer = new BYTE[dwBufferSize]; if (! pNewFileBuffer) { bResult = FALSE; goto end; } CopyMemory(pNewFileBuffer, pFileBuffer, dwCurrentPos); delete[] pFileBuffer; pFileBuffer = pNewFileBuffer; } break; } if (dwCurrentPos < dwWritten ? pFileBuffer[dwCurrentPos] == '\r' || pFileBuffer[dwCurrentPos] == '\n' : bEndOfFile) { if (dwLineStart < dwCurrentPos && ! AddToTail(pFileBuffer + dwLineStart, dwCurrentPos - dwLineStart, true)) { bResult = FALSE; goto end; } if (dwCurrentPos == dwWritten) // bEndOfFile == TRUE, see condition above { bResult = TRUE; goto end; } dwLineStart = dwCurrentPos + 1; } ++dwCurrentPos; } } } end: if (! bResult) FreeEntries(); delete[] pFileBuffer; } CloseHandle(hFile); } else { DWORD dwLastError = GetLastError(); if (dwLastError == ERROR_FILE_NOT_FOUND || dwLastError == ERROR_PATH_NOT_FOUND || GetFileAttributes(pszLogFileName) == INVALID_FILE_ATTRIBUTES) { bResult = TRUE; // ignore missing files } } #ifdef _DEBUG DWORD dwEndTime = GetTickCount(); TCHAR szMessage[128]; _stprintf_s(szMessage, countof(szMessage), _T("CTextLogFile::LoadEntries(): %lu entries, %lu bytes, %lu milliseconds\r\n"), GetNumEntries(), GetNumBytes(), dwEndTime - dwStartTime); OutputDebugString(szMessage); #endif return bResult; }
/** * @param bCrash - true if crash has occurred. * @return true if the log was saved successfully. */ BOOL CTextLogFile::SaveEntries(BOOL /*bCrash*/) { #ifdef _DEBUG DWORD dwStartTime = GetTickCount(); #endif PCTSTR pszLogFileName = GetLogFileName(); HANDLE hFile = CreateFile(pszLogFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; DWORD dwWritten; WriteFile(hFile, g_arrUTF8Preamble, sizeof(g_arrUTF8Preamble), &dwWritten, NULL); CLogEntry* pLogEntry = GetFirstEntry(); while (pLogEntry) { CTextLogEntry* pTextLogEntry = (CTextLogEntry*)pLogEntry; WriteFile(hFile, pTextLogEntry->m_pbData, pTextLogEntry->m_dwSize, &dwWritten, NULL); pLogEntry = pLogEntry->m_pNextEntry; } #ifdef _DEBUG DWORD dwEndTime = GetTickCount(); TCHAR szMessage[128]; _stprintf_s(szMessage, countof(szMessage), _T("CTextLogFile::SaveEntries(): %lu entries, %lu bytes, %lu milliseconds\r\n"), GetNumEntries(), GetNumBytes(), dwEndTime - dwStartTime); OutputDebugString(szMessage); #endif CloseHandle(hFile); return TRUE; }