Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
File: sq.cpp Progetto: 10jul/tnvme
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");
}
Esempio n. 5
0
File: sq.cpp Progetto: 10jul/tnvme
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);
}
Esempio n. 6
0
/**
 * @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;
}
Esempio n. 7
0
/**
 * @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;
}