<commit_before>/**
 * This contains all the "unit"-tests for making sure that everything works.
 */

#define FPL_IMPLEMENTATION
#define FPL_NO_WINDOW
#define FPL_AUTO_NAMESPACE

// @NOTE(final): Any assert should fire immediatly, regardless of the configuration
#define FPL_FORCE_ASSERTIONS
#include "final_platform_layer.hpp"

// @NOTE(final): C++ Standard Library (We dont want to use fpl here, because we want to test it from independent systems)
#include <iostream> // cout
#include <string> // string
#include <varargs.h> // va_list, va_start, va_end

#define ASSERTION_CRASH() {*(int *)0 = 0xBAD;}

struct TestLineAssertionInfo {
	char *filename;
	char *functionName;
	int line;
};

template <typename T>
static void TestAssert(const T &expected, const T &actual, const TestLineAssertionInfo &lineInfo, const std::string &message = "") {
	bool success = (expected == actual);
	if (!success) {
		std::cerr << "Failed assertion in file '" << lineInfo.filename << "', function '" << lineInfo.functionName << "', line " << lineInfo.line;
		if (message.size() > 0) {
			std::cerr << " -> " << message;
		}
		std::cerr << std::endl;
		std::cerr << "Expected type '" << typeid(T).name() << "' of '" << expected << "' but got '" << actual << "'!" << std::endl;
		ASSERTION_CRASH();
	}
}

template <typename T>
static void TestNotAssert(const T &notExpected, const T &actual, const TestLineAssertionInfo &lineInfo, const std::string &message = "") {
	bool success = (notExpected != actual);
	if (!success) {
		std::cerr << "Failed assertion in file '" << lineInfo.filename << "', function '" << lineInfo.functionName << "', line " << lineInfo.line;
		if (message.size() > 0) {
			std::cerr << " -> " << message;
		}
		std::cerr << std::endl;
		std::cerr << "Expected type '" << typeid(T).name() << "' of not '" << notExpected << "' but got '" << actual << "'!" << std::endl;
		ASSERTION_CRASH();
	}
}

static void TestLog(const char *section, const char *format, ...) {
	char buffer[2048];
	va_list argList;
	va_start(argList, format);
	vsprintf_s(buffer, 2048, format, argList);
	va_end(argList);
	std::cout << "[" << section << "] " << buffer << std::endl;
}

#define LAI {__FILE__, __FUNCTION__, __LINE__}
#define FN __FUNCTION__

static void MemoryTests() {
	TestLog(FN, "Test size macros");
	{
		TestAssert<size_t>(0ull, FPL_KILOBYTES(0), LAI, "0 KB");
		TestAssert<size_t>(0ull, FPL_MEGABYTES(0), LAI, "0 MB");
		TestAssert<size_t>(0ull, FPL_GIGABYTES(0), LAI, "0 GB");
		TestAssert<size_t>(0ull, FPL_TERABYTES(0), LAI, "0 TB");
		TestAssert<size_t>(13ull * 1024ull, FPL_KILOBYTES(13), LAI, "13 KB");
		TestAssert<size_t>(137ull * 1024ull * 1024ull, FPL_MEGABYTES(137), LAI, "137 MB");
		TestAssert<size_t>(3ull * 1024ull * 1024ull * 1024ull, FPL_GIGABYTES(3), LAI, "3 GB");
#if defined(FPL_ARCH_X64)
		TestAssert<size_t>(813ull * 1024ull * 1024ull * 1024ull, FPL_GIGABYTES(813), LAI, "813 GB");
		TestAssert<size_t>(2ull * 1024ull * 1024ull * 1024ull * 1024ull, FPL_TERABYTES(2), LAI, "2 TB");
#endif
	}

	TestLog(FN, "Test normal allocation and deallocation");
	{
		size_t memSize = FPL_KILOBYTES(42);
		uint8_t *mem = (uint8_t *)MemoryAllocate(memSize);
		for (size_t i = 0; i < memSize; ++i) {
			uint8_t value = *mem++;
			TestAssert<uint8_t>(0, value, LAI, "42 KB must be zero");
		}
		MemoryFree(mem);
	}
	{
		size_t memSize = FPL_MEGABYTES(512);
		void *mem = MemoryAllocate(memSize);
		TestNotAssert<void *>(mem, nullptr, LAI, "512 MB of memory must be allocatd");
		MemoryFree(mem);
	}

	TestLog(FN, "Test aligned allocation and deallocation");
	{
		size_t memSize = FPL_KILOBYTES(42);
		uint8_t *mem = (uint8_t *)MemoryAlignedAllocate(memSize, 16);
		for (size_t i = 0; i < memSize; ++i) {
			uint8_t value = *(mem + i);
			TestAssert<uint8_t>(0, value, LAI, "42 KB must be zero");
		}
		MemoryAlignedFree(mem);
	}
	{
		size_t memSize = FPL_MEGABYTES(512);
		void *mem = MemoryAlignedAllocate(memSize, 16);
		TestNotAssert<void *>(mem, nullptr, LAI, "512 MB of memory must be allocatd");
		MemoryAlignedFree(mem);
	}
}

static void PathTests() {
	char homePathBuffer[1024] = {};
	GetHomePath(homePathBuffer, FPL_ARRAYCOUNT(homePathBuffer));
	ConsoleFormatOut("Home Path:\n%s\n", homePathBuffer);

	char exeFilePathBuffer[1024] = {};
	GetExecutableFilePath(exeFilePathBuffer, FPL_ARRAYCOUNT(exeFilePathBuffer));
	ConsoleFormatOut("Executable file Path:\n%s\n", exeFilePathBuffer);

	char extractedPathBuffer[1024] = {};
	ExtractFilePath(exeFilePathBuffer, extractedPathBuffer, FPL_ARRAYCOUNT(extractedPathBuffer));
	ConsoleFormatOut("Extracted path:\n%s\n", extractedPathBuffer);

	char *exeFileName = ExtractFileName(exeFilePathBuffer);
	ConsoleFormatOut("Extracted filename:\n%s\n", exeFileName);

	char *exeFileExt = ExtractFileExtension(exeFilePathBuffer);
	ConsoleFormatOut("Extracted extension:\n%s\n", exeFileExt);

	char combinedPathBuffer[1024 * 10] = {};
	CombinePath(combinedPathBuffer, FPL_ARRAYCOUNT(combinedPathBuffer), 4, "Hallo", "Welt", "der", "Programmierer");
	ConsoleFormatOut("Combined path:\n%s\n", combinedPathBuffer);

	char changedFileExtBuffer[1024] = {};
	ChangeFileExtension(exeFilePathBuffer, ".obj", changedFileExtBuffer, FPL_ARRAYCOUNT(changedFileExtBuffer));
	ConsoleFormatOut("Changed file ext 1:\n%s\n", changedFileExtBuffer);
	ChangeFileExtension(exeFileName, ".obj", changedFileExtBuffer, FPL_ARRAYCOUNT(changedFileExtBuffer));
	ConsoleFormatOut("Changed file ext 2:\n%s\n", changedFileExtBuffer);
	ChangeFileExtension(".dll", ".obj", changedFileExtBuffer, FPL_ARRAYCOUNT(changedFileExtBuffer));
	ConsoleFormatOut("Changed file ext 3:\n%s\n", changedFileExtBuffer);
	ChangeFileExtension("", ".obj", changedFileExtBuffer, FPL_ARRAYCOUNT(changedFileExtBuffer));
	ConsoleFormatOut("Changed file ext 4:\n%s\n", changedFileExtBuffer);
	ChangeFileExtension(".dll", "", changedFileExtBuffer, FPL_ARRAYCOUNT(changedFileExtBuffer));
	ConsoleFormatOut("Changed file ext 5:\n%s\n", changedFileExtBuffer);
	ChangeFileExtension("", "", changedFileExtBuffer, FPL_ARRAYCOUNT(changedFileExtBuffer));
	ConsoleFormatOut("Changed file ext 5:\n%s\n", changedFileExtBuffer);
}

static void HardwareTest() {
	char cpuNameBuffer[1024] = {};
	GetProcessorName(cpuNameBuffer, FPL_ARRAYCOUNT(cpuNameBuffer));
	ConsoleFormatOut("Processor name:\n%s\n", cpuNameBuffer);

	uint32_t coreCount = GetProcessorCoreCount();
	ConsoleFormatOut("Processor cores:%d\n", coreCount);
}

static void FilesTest() {
	bool nonExisting = FileExists("C:\\Windows\\i_am_not_existing.lib");
	FPL_ASSERT(!nonExisting);
	bool notepadExists = FileExists("C:\\Windows\\notepad.exe");
	FPL_ASSERT(notepadExists);
	uint32_t emptySize = GetFileSize32("C:\\Windows\\i_am_not_existing.lib");
	FPL_ASSERT(emptySize == 0);
	uint32_t notepadSize = GetFileSize32("C:\\Windows\\notepad.exe");
	FPL_ASSERT(notepadSize > 0);
	FileEntry fileEntry;
	if (ListFilesBegin("C:\\*", &fileEntry)) {
		ConsoleFormatOut("%s\n", fileEntry.path);
		while (ListFilesNext(&fileEntry)) {
			ConsoleFormatOut("%s\n", fileEntry.path);
		}
		ListFilesEnd(&fileEntry);
	}
}

static void TestThreadProc(const ThreadContext &context, void *data) {
	uint32_t ms = (uint32_t)(intptr_t)(data) * 1000;
	ConsoleFormatOut("Thread '%llu' started\n", context.id);
	ThreadSleep(ms);
	ConsoleFormatOut("Thread '%llu' finished\n", context.id);
}

static void ThreadingTest() {
	ThreadContext *threads[3];
	threads[0] = ThreadCreate(TestThreadProc, (void *)1);
	threads[1] = ThreadCreate(TestThreadProc, (void *)2);
	threads[2] = ThreadCreate(TestThreadProc, (void *)3);
	ThreadWaitForMultiple(threads, FPL_ARRAYCOUNT(threads));
}

int main(int argc, char **args) {
	InitPlatform(InitFlags::None);
	MemoryTests();
	ThreadingTest();
	HardwareTest();
	PathTests();
	FilesTest();
	ReleasePlatform();
}<commit_msg>A few fixes for console sample<commit_after>/**
 * This contains all the "unit"-tests for making sure that everything works.
 */

#define FPL_IMPLEMENTATION
#define FPL_NO_WINDOW
#define FPL_AUTO_NAMESPACE

// @NOTE(final): Any assert should fire immediatly, regardless of the configuration
#define FPL_FORCE_ASSERTIONS
#include "final_platform_layer.hpp"

// @NOTE(final): C++ Standard Library (We dont want to use fpl here, because we want to test it from independent systems)
#include <iostream> // cout
#include <string> // string
#include <stdarg.h> // va_list, va_start, va_end
#include <typeinfo> // typeid

#define ASSERTION_CRASH() {*(int *)0 = 0xBAD;}

#if defined(FPL_COMPILER_GCC)
#	define __FUNCTION__ ""
#endif

struct TestLineAssertionInfo {
	char *filename;
	char *functionName;
	int line;
};

template <typename T>
static void TestAssert(const T &expected, const T &actual, const TestLineAssertionInfo &lineInfo, const std::string &message = "") {
	bool success = (expected == actual);
	if (!success) {
		std::cerr << "Failed assertion in file '" << lineInfo.filename << "', function '" << lineInfo.functionName << "', line " << lineInfo.line;
		if (message.size() > 0) {
			std::cerr << " -> " << message;
		}
		std::cerr << std::endl;
		std::cerr << "Expected type '" << typeid(T).name() << "' of '" << expected << "' but got '" << actual << "'!" << std::endl;
		ASSERTION_CRASH();
	}
}

template <typename T>
static void TestNotAssert(const T &notExpected, const T &actual, const TestLineAssertionInfo &lineInfo, const std::string &message = "") {
	bool success = (notExpected != actual);
	if (!success) {
		std::cerr << "Failed assertion in file '" << lineInfo.filename << "', function '" << lineInfo.functionName << "', line " << lineInfo.line;
		if (message.size() > 0) {
			std::cerr << " -> " << message;
		}
		std::cerr << std::endl;
		std::cerr << "Expected type '" << typeid(T).name() << "' of not '" << notExpected << "' but got '" << actual << "'!" << std::endl;
		ASSERTION_CRASH();
	}
}

static void TestLog(const char *section, const char *format, ...) {
	char buffer[2048];
	va_list argList;
	va_start(argList, format);
#if __STDC_WANT_SECURE_LIB__
	vsprintf_s(buffer, FPL_ARRAYCOUNT(buffer), format, argList);
#else
	vsprintf(buffer, format, argList);
#endif
	va_end(argList);
	std::cout << "[" << section << "] " << buffer << std::endl;
}

#define LAI {__FILE__, __FUNCTION__, __LINE__}
#define FN __FUNCTION__

static void MemoryTests() {
	TestLog(FN, "Test size macros");
	{
		TestAssert<size_t>(0ull, FPL_KILOBYTES(0), LAI, "0 KB");
		TestAssert<size_t>(0ull, FPL_MEGABYTES(0), LAI, "0 MB");
		TestAssert<size_t>(0ull, FPL_GIGABYTES(0), LAI, "0 GB");
		TestAssert<size_t>(0ull, FPL_TERABYTES(0), LAI, "0 TB");
		TestAssert<size_t>(13ull * 1024ull, FPL_KILOBYTES(13), LAI, "13 KB");
		TestAssert<size_t>(137ull * 1024ull * 1024ull, FPL_MEGABYTES(137), LAI, "137 MB");
		TestAssert<size_t>(3ull * 1024ull * 1024ull * 1024ull, FPL_GIGABYTES(3), LAI, "3 GB");
#if defined(FPL_ARCH_X64)
		TestAssert<size_t>(813ull * 1024ull * 1024ull * 1024ull, FPL_GIGABYTES(813), LAI, "813 GB");
		TestAssert<size_t>(2ull * 1024ull * 1024ull * 1024ull * 1024ull, FPL_TERABYTES(2), LAI, "2 TB");
#endif
	}

	TestLog(FN, "Test normal allocation and deallocation");
	{
		size_t memSize = FPL_KILOBYTES(42);
		uint8_t *mem = (uint8_t *)MemoryAllocate(memSize);
		for (size_t i = 0; i < memSize; ++i) {
			uint8_t value = *mem++;
			TestAssert<uint8_t>(0, value, LAI, "42 KB must be zero");
		}
		MemoryFree(mem);
	}
	{
		size_t memSize = FPL_MEGABYTES(512);
		void *mem = MemoryAllocate(memSize);
		TestNotAssert<void *>(mem, nullptr, LAI, "512 MB of memory must be allocatd");
		MemoryFree(mem);
	}

	TestLog(FN, "Test aligned allocation and deallocation");
	{
		size_t memSize = FPL_KILOBYTES(42);
		uint8_t *mem = (uint8_t *)MemoryAlignedAllocate(memSize, 16);
		for (size_t i = 0; i < memSize; ++i) {
			uint8_t value = *(mem + i);
			TestAssert<uint8_t>(0, value, LAI, "42 KB must be zero");
		}
		MemoryAlignedFree(mem);
	}
	{
		size_t memSize = FPL_MEGABYTES(512);
		void *mem = MemoryAlignedAllocate(memSize, 16);
		TestNotAssert<void *>(mem, nullptr, LAI, "512 MB of memory must be allocatd");
		MemoryAlignedFree(mem);
	}
}

static void PathTests() {
	char homePathBuffer[1024] = {};
	GetHomePath(homePathBuffer, FPL_ARRAYCOUNT(homePathBuffer));
	ConsoleFormatOut("Home Path:\n%s\n", homePathBuffer);

	char exeFilePathBuffer[1024] = {};
	GetExecutableFilePath(exeFilePathBuffer, FPL_ARRAYCOUNT(exeFilePathBuffer));
	ConsoleFormatOut("Executable file Path:\n%s\n", exeFilePathBuffer);

	char extractedPathBuffer[1024] = {};
	ExtractFilePath(exeFilePathBuffer, extractedPathBuffer, FPL_ARRAYCOUNT(extractedPathBuffer));
	ConsoleFormatOut("Extracted path:\n%s\n", extractedPathBuffer);

	char *exeFileName = ExtractFileName(exeFilePathBuffer);
	ConsoleFormatOut("Extracted filename:\n%s\n", exeFileName);

	char *exeFileExt = ExtractFileExtension(exeFilePathBuffer);
	ConsoleFormatOut("Extracted extension:\n%s\n", exeFileExt);

	char combinedPathBuffer[1024 * 10] = {};
	CombinePath(combinedPathBuffer, FPL_ARRAYCOUNT(combinedPathBuffer), 4, "Hallo", "Welt", "der", "Programmierer");
	ConsoleFormatOut("Combined path:\n%s\n", combinedPathBuffer);

	char changedFileExtBuffer[1024] = {};
	ChangeFileExtension(exeFilePathBuffer, ".obj", changedFileExtBuffer, FPL_ARRAYCOUNT(changedFileExtBuffer));
	ConsoleFormatOut("Changed file ext 1:\n%s\n", changedFileExtBuffer);
	ChangeFileExtension(exeFileName, ".obj", changedFileExtBuffer, FPL_ARRAYCOUNT(changedFileExtBuffer));
	ConsoleFormatOut("Changed file ext 2:\n%s\n", changedFileExtBuffer);
	ChangeFileExtension(".dll", ".obj", changedFileExtBuffer, FPL_ARRAYCOUNT(changedFileExtBuffer));
	ConsoleFormatOut("Changed file ext 3:\n%s\n", changedFileExtBuffer);
	ChangeFileExtension("", ".obj", changedFileExtBuffer, FPL_ARRAYCOUNT(changedFileExtBuffer));
	ConsoleFormatOut("Changed file ext 4:\n%s\n", changedFileExtBuffer);
	ChangeFileExtension(".dll", "", changedFileExtBuffer, FPL_ARRAYCOUNT(changedFileExtBuffer));
	ConsoleFormatOut("Changed file ext 5:\n%s\n", changedFileExtBuffer);
	ChangeFileExtension("", "", changedFileExtBuffer, FPL_ARRAYCOUNT(changedFileExtBuffer));
	ConsoleFormatOut("Changed file ext 5:\n%s\n", changedFileExtBuffer);
}

static void HardwareTest() {
	char cpuNameBuffer[1024] = {};
	GetProcessorName(cpuNameBuffer, FPL_ARRAYCOUNT(cpuNameBuffer));
	ConsoleFormatOut("Processor name:\n%s\n", cpuNameBuffer);

	uint32_t coreCount = GetProcessorCoreCount();
	ConsoleFormatOut("Processor cores:%d\n", coreCount);
}

static void FilesTest() {
	bool nonExisting = FileExists("C:\\Windows\\i_am_not_existing.lib");
	FPL_ASSERT(!nonExisting);
	bool notepadExists = FileExists("C:\\Windows\\notepad.exe");
	FPL_ASSERT(notepadExists);
	uint32_t emptySize = GetFileSize32("C:\\Windows\\i_am_not_existing.lib");
	FPL_ASSERT(emptySize == 0);
	uint32_t notepadSize = GetFileSize32("C:\\Windows\\notepad.exe");
	FPL_ASSERT(notepadSize > 0);
	FileEntry fileEntry;
	if (ListFilesBegin("C:\\*", &fileEntry)) {
		ConsoleFormatOut("%s\n", fileEntry.path);
		while (ListFilesNext(&fileEntry)) {
			ConsoleFormatOut("%s\n", fileEntry.path);
		}
		ListFilesEnd(&fileEntry);
	}
}

static void TestThreadProc(const ThreadContext &context, void *data) {
	uint32_t ms = (uint32_t)(intptr_t)(data) * 1000;
	ConsoleFormatOut("Thread '%llu' started\n", context.id);
	ThreadSleep(ms);
	ConsoleFormatOut("Thread '%llu' finished\n", context.id);
}

static void ThreadingTest() {
	ThreadContext *threads[3];
	threads[0] = ThreadCreate(TestThreadProc, (void *)1);
	threads[1] = ThreadCreate(TestThreadProc, (void *)2);
	threads[2] = ThreadCreate(TestThreadProc, (void *)3);
	ThreadWaitForMultiple(threads, FPL_ARRAYCOUNT(threads));
}

int main(int argc, char **args) {
	InitPlatform(InitFlags::None);
	MemoryTests();
	ThreadingTest();
	HardwareTest();
	PathTests();
	FilesTest();
	ReleasePlatform();
}
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <mitkPolhemusInterface.h>

BYTE  MotionBuf[0x1FA400];

mitk::PolhemusInterface::PolhemusInterface()
{

  m_pdiDev.SetPnoBuffer(MotionBuf, 0x1FA400);
  m_pdiDev.SetMetric(true); //use cm instead of inches
  /* some settings, not sure if we need them
  m_pdiDev.Trace(TRUE, 7);
  CPDImdat pdiMDat;
  pdiMDat.Empty();
  pdiMDat.Append(PDI_MODATA_FRAMECOUNT);
  pdiMDat.Append(PDI_MODATA_POS);
  pdiMDat.Append(PDI_MODATA_ORI);
  m_pdiDev.SetSDataList(-1, pdiMDat);
  */
}

mitk::PolhemusInterface::~PolhemusInterface()
{

}

bool mitk::PolhemusInterface::StartTracking()
{
  /* some setting / not sure if we need them
  LPCTSTR	szWindowClass = _T("PDIconsoleWinClass");
  HINSTANCE hInst = GetModuleHandle(0);
  HWND	hwnd = CreateWindowEx(
    WS_EX_NOACTIVATE,//WS_EX_STATICEDGE, //
    szWindowClass,
    _T("MyWindowName"),
    WS_POPUP,
    0, 0, 1, 1,
    HWND_MESSAGE,
    0,
    hInst,
    0);
  */
  m_continousTracking = true;
  return m_pdiDev.StartContPno(0);
}

bool mitk::PolhemusInterface::StopTracking()
{
  m_continousTracking = false;
  return true;
}

bool mitk::PolhemusInterface::Connect()
{
  if (m_pdiDev.CnxReady()) { return true; }

  ePiCommType eType = m_pdiDev.DiscoverCnx();
  switch (eType)
  {
  case PI_CNX_USB:
    MITK_INFO << "USB Connection: " << m_pdiDev.GetLastResultStr();
    break;
  case PI_CNX_SERIAL:
    MITK_INFO << "Serial Connection: " << m_pdiDev.GetLastResultStr();
    break;
  default:
    MITK_INFO << "DiscoverCnx result: " << m_pdiDev.GetLastResultStr();
    break;
  }

  return m_pdiDev.CnxReady();
}

bool mitk::PolhemusInterface::Disconnect()
{
  if (m_continousTracking)
  {
    m_continousTracking = false;
    if (!m_pdiDev.Disconnect()) return false;
  }
  return true;
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::GetLastFrame()
{
  PBYTE pBuf;
  DWORD dwSize;

  //read one frame
  if (!m_pdiDev.LastPnoPtr(pBuf, dwSize)) {MITK_WARN << m_pdiDev.GetLastResultStr();}

  std::vector<mitk::PolhemusInterface::trackingData> returnValue = ParsePolhemusRawData(pBuf, dwSize);

  if (returnValue.empty()) { MITK_WARN << "Cannot parse data / no tools present"; }

  return returnValue;
}

unsigned int mitk::PolhemusInterface::GetNumberOfTools()
{
  if (m_continousTracking) return GetLastFrame().size();
  else return GetSingleFrame().size();
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::GetSingleFrame()
{
  if (m_continousTracking) return std::vector<mitk::PolhemusInterface::trackingData>();

  PBYTE pBuf;
  DWORD dwSize;

  //read one frame
  if (!m_pdiDev.ReadSinglePnoBuf(pBuf, dwSize)) { MITK_WARN << m_pdiDev.GetLastResultStr(); }

  return ParsePolhemusRawData(pBuf, dwSize);
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::ParsePolhemusRawData(PBYTE pBuf, DWORD dwSize)
{
  std::vector<mitk::PolhemusInterface::trackingData> returnValue;

  DWORD i = 0;

  while (i<dwSize)
  {
    BYTE ucSensor = pBuf[i + 2];
    SHORT shSize = pBuf[i + 6];

    // skip rest of header
    i += 8;

    PDWORD pFC = (PDWORD)(&pBuf[i]);
    PFLOAT pPno = (PFLOAT)(&pBuf[i + 4]);

    mitk::PolhemusInterface::trackingData currentTrackingData;

    currentTrackingData.pos[0] = pPno[0] * 10;
    currentTrackingData.pos[1] = pPno[1] * 10;
    currentTrackingData.pos[2] = pPno[2] * 10;

    double azimuthAngle = pPno[3] / 180 * 3.14;
    double elevationAngle = pPno[4] / 180 * 3.14;
    double rollAngle = pPno[5] / 180 * 3.14;
    vnl_quaternion<double> eulerQuat(rollAngle, elevationAngle, azimuthAngle);
    currentTrackingData.rot = eulerQuat;

    returnValue.push_back(currentTrackingData);
    i += shSize;
  }
  return returnValue;
}
<commit_msg>added math.h for PI<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <mitkPolhemusInterface.h>
#define _USE_MATH_DEFINES
#include <math.h>

BYTE  MotionBuf[0x1FA400];

mitk::PolhemusInterface::PolhemusInterface()
{

  m_pdiDev.SetPnoBuffer(MotionBuf, 0x1FA400);
  m_pdiDev.SetMetric(true); //use cm instead of inches
  /* some settings, not sure if we need them
  m_pdiDev.Trace(TRUE, 7);
  CPDImdat pdiMDat;
  pdiMDat.Empty();
  pdiMDat.Append(PDI_MODATA_FRAMECOUNT);
  pdiMDat.Append(PDI_MODATA_POS);
  pdiMDat.Append(PDI_MODATA_ORI);
  m_pdiDev.SetSDataList(-1, pdiMDat);
  */
}

mitk::PolhemusInterface::~PolhemusInterface()
{

}

bool mitk::PolhemusInterface::StartTracking()
{
  /* some setting / not sure if we need them
  LPCTSTR	szWindowClass = _T("PDIconsoleWinClass");
  HINSTANCE hInst = GetModuleHandle(0);
  HWND	hwnd = CreateWindowEx(
    WS_EX_NOACTIVATE,//WS_EX_STATICEDGE, //
    szWindowClass,
    _T("MyWindowName"),
    WS_POPUP,
    0, 0, 1, 1,
    HWND_MESSAGE,
    0,
    hInst,
    0);
  */
  m_continousTracking = true;
  return m_pdiDev.StartContPno(0);
}

bool mitk::PolhemusInterface::StopTracking()
{
  m_continousTracking = false;
  return true;
}

bool mitk::PolhemusInterface::Connect()
{
  if (m_pdiDev.CnxReady()) { return true; }

  ePiCommType eType = m_pdiDev.DiscoverCnx();
  switch (eType)
  {
  case PI_CNX_USB:
    MITK_INFO << "USB Connection: " << m_pdiDev.GetLastResultStr();
    break;
  case PI_CNX_SERIAL:
    MITK_INFO << "Serial Connection: " << m_pdiDev.GetLastResultStr();
    break;
  default:
    MITK_INFO << "DiscoverCnx result: " << m_pdiDev.GetLastResultStr();
    break;
  }

  return m_pdiDev.CnxReady();
}

bool mitk::PolhemusInterface::Disconnect()
{
  if (m_continousTracking)
  {
    m_continousTracking = false;
    if (!m_pdiDev.Disconnect()) return false;
  }
  return true;
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::GetLastFrame()
{
  PBYTE pBuf;
  DWORD dwSize;

  //read one frame
  if (!m_pdiDev.LastPnoPtr(pBuf, dwSize)) {MITK_WARN << m_pdiDev.GetLastResultStr();}

  std::vector<mitk::PolhemusInterface::trackingData> returnValue = ParsePolhemusRawData(pBuf, dwSize);

  if (returnValue.empty()) { MITK_WARN << "Cannot parse data / no tools present"; }

  return returnValue;
}

unsigned int mitk::PolhemusInterface::GetNumberOfTools()
{
  if (m_continousTracking) return GetLastFrame().size();
  else return GetSingleFrame().size();
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::GetSingleFrame()
{
  if (m_continousTracking) return std::vector<mitk::PolhemusInterface::trackingData>();

  PBYTE pBuf;
  DWORD dwSize;

  //read one frame
  if (!m_pdiDev.ReadSinglePnoBuf(pBuf, dwSize)) { MITK_WARN << m_pdiDev.GetLastResultStr(); }

  return ParsePolhemusRawData(pBuf, dwSize);
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::ParsePolhemusRawData(PBYTE pBuf, DWORD dwSize)
{
  std::vector<mitk::PolhemusInterface::trackingData> returnValue;

  DWORD i = 0;

  while (i<dwSize)
  {
    BYTE ucSensor = pBuf[i + 2];
    SHORT shSize = pBuf[i + 6];

    // skip rest of header
    i += 8;

    PDWORD pFC = (PDWORD)(&pBuf[i]);
    PFLOAT pPno = (PFLOAT)(&pBuf[i + 4]);

    mitk::PolhemusInterface::trackingData currentTrackingData;

    currentTrackingData.pos[0] = pPno[0] * 10; //from cm to mm
    currentTrackingData.pos[1] = pPno[1] * 10;
    currentTrackingData.pos[2] = pPno[2] * 10;

    double azimuthAngle = pPno[3] / 180 * M_PI; //from degree to rad
    double elevationAngle = pPno[4] / 180 * M_PI;
    double rollAngle = pPno[5] / 180 * M_PI;
    vnl_quaternion<double> eulerQuat(rollAngle, elevationAngle, azimuthAngle);
    currentTrackingData.rot = eulerQuat;

    returnValue.push_back(currentTrackingData);
    i += shSize;
  }
  return returnValue;
}
<|endoftext|>


<commit_before>/*
 *  AvanceDB - an in-memory database similar to Apache CouchDB
 *  Copyright (C) 2015-2017 Ripcord Software
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "http_server_log.h"

#include <iostream>
#include <cstdio>

#include <boost/format.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/atomic.hpp>
#include <boost/thread.hpp>

#include "termcolor/termcolor.hpp"

#include "set_thread_name.h"
#include "config.h"

static const unsigned cumulativeSecsPerMonth[12] = { 2678400, 5097600, 7776000, 10368000, 13046400, 15638400, 18316800, 20995200, 23587200, 26265600, 28857600, 31536000 };
static const unsigned cumulativeSecsPerMonthLeap[12] = { 2678400, 5184000, 7862400, 10454400, 13132800, 15724800, 18403200, 21081600, 23673600, 26352000, 28944000, 31622400 };

struct LogRow {
    LogRow() : status(0) {
        data[0] = 0;
    }

    int status;
    char data[2048];
};

static bool colorEnabled = false;
static const unsigned maxLogRows = 4096;
static LogRow logRows[maxLogRows];
static boost::atomic<unsigned> writeRowIndex;
static unsigned readRowIndex = 0;

static boost::once_flag startLogging = BOOST_ONCE_INIT;

static void StreamWriterThread() {
    SetThreadName::Set("avancedb-httplog");

    try {
        while (true) {
            boost::this_thread::sleep_for(boost::chrono::seconds(2));

            int lastStatus = 200;
            auto lastRowIndex = writeRowIndex.load();

            while (readRowIndex < lastRowIndex) {
                for (auto i = readRowIndex; i < lastRowIndex; ++i) {
                    auto& row = logRows[i % maxLogRows];

                    if (colorEnabled && row.status != lastStatus) {
                        if (row.status >= 500) {
                            std::cout << termcolor::red;
                        } else if (row.status >= 400) {
                            std::cout << termcolor::grey << termcolor::bold;
                        } else if (row.status >= 300) {
                            std::cout << termcolor::yellow;
                        } else {
                            std::cout << termcolor::reset;
                        }

                        lastStatus = row.status;
                    }

                    std::cout << row.data << "\n";
                }

                readRowIndex = lastRowIndex;
                lastRowIndex = writeRowIndex.load();
            }

            if (colorEnabled) {
                std::cout << termcolor::reset;
            }

            std::cout << std::flush;
        }
    } catch (boost::thread_interrupted&) {
    }
}

static void StartLogging() {
    colorEnabled = Config::Process::Color();

    boost::thread logThread(StreamWriterThread);
    logThread.detach();
}

void HttpServerLog::Append(rs::httpserver::socket_ptr socket, rs::httpserver::request_ptr request, rs::httpserver::response_ptr response, const std::time_t& start, long duration) {
    // start the log thread if it isn't already running
    boost::call_once(StartLogging, startLogging);

    int year, month, day, hour, min, sec;
    GetTimestamp(start, year, month, day, hour, min, sec);

    const auto queryString = request->getHeaders()->getQueryString();

    const auto localAddr = socket->getLocalEndpoint().address().to_string();
    const auto remoteAddr = socket->getRemoteEndpoint().address().to_string();

    auto index = writeRowIndex++;
    index %= maxLogRows;

    // TODO: optimize the string formatting to reduce ad-hoc allocations and re-use already known string values (dates, etc.)
    logRows[index].status = response->getStatusCode();
    std::snprintf(logRows[index].data, sizeof(logRows[0].data),
        "%04d-%02d-%02d %02d:%02d:%02dZ %s %s %s %s %u %s %s %d %u",
        year, month, day, hour, min, sec,
        localAddr.c_str(),
        request->getMethod().c_str(),
        request->getUri().c_str(),
        queryString.size() > 0 ? queryString.c_str() : "-",
        socket->getLocalEndpoint().port(),
        remoteAddr.c_str(),
        boost::replace_all_copy(request->getHeaders()->getUserAgent(), " ", "+").c_str(),
        response->getStatusCode(),
        duration);
}

void HttpServerLog::GetTimestamp(const std::time_t& time, int& year, int& month, int& day, int& hour, int& min, int& sec) {
    auto totalDays = time / 86400;
    auto elapsedYears = (long)(totalDays / 365.25);
    auto leapYears = ((long)elapsedYears) / 4;
    auto yearStart = ((elapsedYears - leapYears) * 31536000) + (leapYears * 31622400);
    auto elapsedSecondsThisYear = time - yearStart;

    year = 1970 + elapsedYears;
    auto isLeap = (year % 4) == 0;
    month = GetMonth(elapsedSecondsThisYear, isLeap);
    day = GetDay(elapsedSecondsThisYear, month, isLeap);

    ++month;
    ++day;

    hour = (time % (24 * 60 * 60)) / (60 * 60);
    min = (time % (60 * 60)) / 60;
    sec = time % 60;
}

unsigned HttpServerLog::GetMonth(long elapsedSeconds, bool isLeap) {
    const unsigned* lookup = isLeap ? cumulativeSecsPerMonthLeap : cumulativeSecsPerMonth;

    int i = 6, left = 0, right = 12;
    for (; left < right; i = left + ((right - left) / 2)) {
        if (elapsedSeconds < lookup[i]) {
            right = i - 1;
        } else {
            left = i + 1;
        }
    }

    return i;
}

unsigned HttpServerLog::GetDay(long elapsedSeconds, unsigned month, bool isLeap) {
    const unsigned* lookup = isLeap ? cumulativeSecsPerMonthLeap : cumulativeSecsPerMonth;

    auto dayMod = month > 0 ? elapsedSeconds - lookup[month - 1] : elapsedSeconds;
    auto day = dayMod / 86400;
    return day;
}<commit_msg>If there isn't a user-agent emit "-" into the logs<commit_after>/*
 *  AvanceDB - an in-memory database similar to Apache CouchDB
 *  Copyright (C) 2015-2017 Ripcord Software
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "http_server_log.h"

#include <iostream>
#include <cstdio>

#include <boost/format.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/atomic.hpp>
#include <boost/thread.hpp>

#include "termcolor/termcolor.hpp"

#include "set_thread_name.h"
#include "config.h"

static const unsigned cumulativeSecsPerMonth[12] = { 2678400, 5097600, 7776000, 10368000, 13046400, 15638400, 18316800, 20995200, 23587200, 26265600, 28857600, 31536000 };
static const unsigned cumulativeSecsPerMonthLeap[12] = { 2678400, 5184000, 7862400, 10454400, 13132800, 15724800, 18403200, 21081600, 23673600, 26352000, 28944000, 31622400 };

struct LogRow {
    LogRow() : status(0) {
        data[0] = 0;
    }

    int status;
    char data[2048];
};

static bool colorEnabled = false;
static const unsigned maxLogRows = 4096;
static LogRow logRows[maxLogRows];
static boost::atomic<unsigned> writeRowIndex;
static unsigned readRowIndex = 0;

static boost::once_flag startLogging = BOOST_ONCE_INIT;

static void StreamWriterThread() {
    SetThreadName::Set("avancedb-httplog");

    try {
        while (true) {
            boost::this_thread::sleep_for(boost::chrono::seconds(2));

            int lastStatus = 200;
            auto lastRowIndex = writeRowIndex.load();

            while (readRowIndex < lastRowIndex) {
                for (auto i = readRowIndex; i < lastRowIndex; ++i) {
                    auto& row = logRows[i % maxLogRows];

                    if (colorEnabled && row.status != lastStatus) {
                        if (row.status >= 500) {
                            std::cout << termcolor::red;
                        } else if (row.status >= 400) {
                            std::cout << termcolor::grey << termcolor::bold;
                        } else if (row.status >= 300) {
                            std::cout << termcolor::yellow;
                        } else {
                            std::cout << termcolor::reset;
                        }

                        lastStatus = row.status;
                    }

                    std::cout << row.data << "\n";
                }

                readRowIndex = lastRowIndex;
                lastRowIndex = writeRowIndex.load();
            }

            if (colorEnabled) {
                std::cout << termcolor::reset;
            }

            std::cout << std::flush;
        }
    } catch (boost::thread_interrupted&) {
    }
}

static void StartLogging() {
    colorEnabled = Config::Process::Color();

    boost::thread logThread(StreamWriterThread);
    logThread.detach();
}

void HttpServerLog::Append(rs::httpserver::socket_ptr socket, rs::httpserver::request_ptr request, rs::httpserver::response_ptr response, const std::time_t& start, long duration) {
    // start the log thread if it isn't already running
    boost::call_once(StartLogging, startLogging);

    int year, month, day, hour, min, sec;
    GetTimestamp(start, year, month, day, hour, min, sec);

    const auto& queryString = request->getHeaders()->getQueryString();

    auto localAddr = socket->getLocalEndpoint().address().to_string();
    auto remoteAddr = socket->getRemoteEndpoint().address().to_string();

    auto userAgent = boost::replace_all_copy(request->getHeaders()->getUserAgent(), " ", "+");

    auto index = writeRowIndex++;
    index %= maxLogRows;

    // TODO: optimize the string formatting to reduce ad-hoc allocations and re-use already known string values (dates, etc.)
    logRows[index].status = response->getStatusCode();
    std::snprintf(logRows[index].data, sizeof(logRows[0].data),
        "%04d-%02d-%02d %02d:%02d:%02dZ %s %s %s %s %u %s %s %d %u",
        year, month, day, hour, min, sec,
        localAddr.c_str(),
        request->getMethod().c_str(),
        request->getUri().c_str(),
        queryString.size() > 0 ? queryString.c_str() : "-",
        socket->getLocalEndpoint().port(),
        remoteAddr.c_str(),
        userAgent.size() > 0 ? userAgent.c_str() : "-",
        response->getStatusCode(),
        duration);
}

void HttpServerLog::GetTimestamp(const std::time_t& time, int& year, int& month, int& day, int& hour, int& min, int& sec) {
    auto totalDays = time / 86400;
    auto elapsedYears = (long)(totalDays / 365.25);
    auto leapYears = ((long)elapsedYears) / 4;
    auto yearStart = ((elapsedYears - leapYears) * 31536000) + (leapYears * 31622400);
    auto elapsedSecondsThisYear = time - yearStart;

    year = 1970 + elapsedYears;
    auto isLeap = (year % 4) == 0;
    month = GetMonth(elapsedSecondsThisYear, isLeap);
    day = GetDay(elapsedSecondsThisYear, month, isLeap);

    ++month;
    ++day;

    hour = (time % (24 * 60 * 60)) / (60 * 60);
    min = (time % (60 * 60)) / 60;
    sec = time % 60;
}

unsigned HttpServerLog::GetMonth(long elapsedSeconds, bool isLeap) {
    const unsigned* lookup = isLeap ? cumulativeSecsPerMonthLeap : cumulativeSecsPerMonth;

    int i = 6, left = 0, right = 12;
    for (; left < right; i = left + ((right - left) / 2)) {
        if (elapsedSeconds < lookup[i]) {
            right = i - 1;
        } else {
            left = i + 1;
        }
    }

    return i;
}

unsigned HttpServerLog::GetDay(long elapsedSeconds, unsigned month, bool isLeap) {
    const unsigned* lookup = isLeap ? cumulativeSecsPerMonthLeap : cumulativeSecsPerMonth;

    auto dayMod = month > 0 ? elapsedSeconds - lookup[month - 1] : elapsedSeconds;
    auto day = dayMod / 86400;
    return day;
}<|endoftext|>


<commit_before>#include <combinations_with_replacement.hpp>

#include <vector>
#include <string>
#include <iostream>
#include <array>

using iter::combinations_with_replacement;

int main() {
    std::vector<int> v = {1,2,3,};
    for (auto i : combinations_with_replacement(v,4)) {
        for (auto j : i ) std::cout << j << " ";
        std::cout<<std::endl;
    }

    for (auto i : combinations_with_replacement(std::vector<int>{1,2,3},4)) {
        for (auto j : i ) std::cout << j << " ";
        std::cout<<std::endl;
    }

    for (auto i : combinations_with_replacement({1,2,3,4},4)) {
        for (auto j : i ) std::cout << j << " ";
        std::cout<<std::endl;
    }

#if 0
    for (auto i : combinations_with_replacement(v,1)) {
        //std::cout << i << std::endl;
        for (auto j : i ) std::cout << j << " ";
        std::cout<<std::endl;
    }
#endif
    return 0;
}
<commit_msg>adds test with static array<commit_after>#include <combinations_with_replacement.hpp>

#include <vector>
#include <string>
#include <iostream>
#include <array>

using iter::combinations_with_replacement;

int main() {
    std::vector<int> v = {1,2,3,};
    for (auto i : combinations_with_replacement(v,4)) {
        for (auto j : i ) std::cout << j << " ";
        std::cout<<std::endl;
    }

    std::cout << "with temporary\n";
    for (auto i : combinations_with_replacement(std::vector<int>{1,2,3},4)) {
        for (auto j : i ) std::cout << j << " ";
        std::cout<<std::endl;
    }

    std::cout << "with init list\n";
    for (auto i : combinations_with_replacement({1,2,3},4)) {
        for (auto j : i ) std::cout << j << " ";
        std::cout<<std::endl;
    }

    std::cout << "with static array\n";
    int arr[] = {1, 2, 3};
    for (auto i : combinations_with_replacement(arr,4)) {
        for (auto j : i ) std::cout << j << " ";
        std::cout<<std::endl;
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "FileSystem.h"
#include "LogUnimpl.h"

#include <fuse.h>
#include <iostream>
#include <cstddef>
#include <string>

using RT11FS::FileSystem;

using std::cerr;
using std::endl;
using std::string;

namespace {
struct rt11_config
{
  char *image;
  int listdir;
};

static auto getFS()
{
  return reinterpret_cast<FileSystem*>(fuse_get_context()->private_data);
}

auto rt11_getattr(const char *path, struct stat *stbuf) -> int
{
  return getFS()->getattr(path, stbuf);
}

auto rt11_fgetattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi) -> int
{
  return getFS()->fgetattr(path, stbuf, fi);
}

auto rt11_statfs(const char *path, struct statvfs *vfs) -> int
{
  return getFS()->statfs(path, vfs);
}

auto rt11_chmod(const char *path, mode_t mode) -> int
{
  return getFS()->chmod(path, mode);
}

<<<<<<< HEAD
auto rt11_unlink(const char *path) -> int
{
  return getFS()->unlink(path);
=======
auto rt11_rename(const char *oldName, const char *newName) -> int
{
  return getFS()->rename(oldName, newName);
>>>>>>> rename
}

auto rt11_opendir(const char *, struct fuse_file_info *) -> int
{
  return 0;
}

auto rt11_releasedir(const char *, struct fuse_file_info *) -> int
{
  return 0;
}

auto rt11_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
  off_t offset, struct fuse_file_info *fi) -> int
{
  return getFS()->readdir(path, buf, filler, offset, fi);
}

auto rt11_open(const char *path, struct fuse_file_info *fi)
{
  return getFS()->open(path, fi);
}

auto rt11_release(const char *path, struct fuse_file_info *fi)
{
  return getFS()->release(path, fi);
}

auto rt11_ftruncate(const char *path, off_t size, struct fuse_file_info *fi) -> int
{
  return getFS()->ftruncate(path, size, fi);
}

auto rt11_read(const char *path, char *buf, size_t count, off_t offset, struct fuse_file_info *fi)
{
  return getFS()->read(path, buf, count, offset, fi);
}

auto rt11_write(const char *path, const char *buf, size_t count, off_t offset, struct fuse_file_info *fi)
{
  return getFS()->write(path, buf, count, offset, fi);
}

auto rt11_fsync(const char *path, int isdatasync, struct fuse_file_info *fi)
{
  return getFS()->fsync(path, isdatasync, fi);
}

auto build_oper(struct fuse_operations *oper)
{
  add_unimpl(oper);

  oper->getattr = &rt11_getattr;
  oper->fgetattr = &rt11_fgetattr;
  oper->statfs = &rt11_statfs;
  oper->chmod = &rt11_chmod;
  oper->unlink = &rt11_unlink;
  oper->rename = &rt11_rename;
  oper->opendir = &rt11_opendir;
  oper->releasedir = &rt11_releasedir;
  oper->readdir = &rt11_readdir;
  oper->open = &rt11_open;
  oper->release = &rt11_release;
  oper->ftruncate = &rt11_ftruncate;
  oper->read = &rt11_read;
  oper->write = &rt11_write;
  oper->fsync = &rt11_fsync;
}

auto usage(const string &program)
{
  cerr << "usage: " << program << " disk-image mountpoint" << endl;
  exit(1);
}

struct fuse_opt rt11_opts[] =
{
  { "-i %s", offsetof(struct rt11_config, image), 0 },
  { "-d",    offsetof(struct rt11_config, listdir), 1},
  FUSE_OPT_END,
};

}

auto main(int argc, char *argv[]) -> int
{
  int exitcode;

  struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
  struct fuse_operations rt11_oper;
  struct rt11_config config;

  memset(&config, 0, sizeof(config));

  if (fuse_opt_parse(&args, &config, rt11_opts, NULL) == -1) {
    usage(argv[0]);
  }

  if (config.image == NULL) {
    cerr << argv[0] << ": must specify an image to mount" << endl;
    usage(argv[0]);
  }

  // make FUSE responsible for enforcing permission bits
  fuse_opt_add_arg(&args, "-odefault_permissions");

  // the file system isn't thread safe; make FUSE serialize requests
  // (it isn't likely that perf will be enough of an issues that this will ever matter)
  fuse_opt_add_arg(&args, "-s");

  FileSystem fs {config.image};

  if (config.listdir) {
    fs.lsdir();
    return 0;
  }

  build_oper(&rt11_oper);
  exitcode = fuse_main(args.argc, args.argv, &rt11_oper, &fs);

  fuse_opt_free_args(&args);
  return exitcode;
}<commit_msg>Fix merge<commit_after>#include "FileSystem.h"
#include "LogUnimpl.h"

#include <fuse.h>
#include <iostream>
#include <cstddef>
#include <string>

using RT11FS::FileSystem;

using std::cerr;
using std::endl;
using std::string;

namespace {
struct rt11_config
{
  char *image;
  int listdir;
};

static auto getFS()
{
  return reinterpret_cast<FileSystem*>(fuse_get_context()->private_data);
}

auto rt11_getattr(const char *path, struct stat *stbuf) -> int
{
  return getFS()->getattr(path, stbuf);
}

auto rt11_fgetattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi) -> int
{
  return getFS()->fgetattr(path, stbuf, fi);
}

auto rt11_statfs(const char *path, struct statvfs *vfs) -> int
{
  return getFS()->statfs(path, vfs);
}

auto rt11_chmod(const char *path, mode_t mode) -> int
{
  return getFS()->chmod(path, mode);
}

auto rt11_unlink(const char *path) -> int
{
  return getFS()->unlink(path);
}

auto rt11_rename(const char *oldName, const char *newName) -> int
{
  return getFS()->rename(oldName, newName);
}

auto rt11_opendir(const char *, struct fuse_file_info *) -> int
{
  return 0;
}

auto rt11_releasedir(const char *, struct fuse_file_info *) -> int
{
  return 0;
}

auto rt11_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
  off_t offset, struct fuse_file_info *fi) -> int
{
  return getFS()->readdir(path, buf, filler, offset, fi);
}

auto rt11_open(const char *path, struct fuse_file_info *fi)
{
  return getFS()->open(path, fi);
}

auto rt11_release(const char *path, struct fuse_file_info *fi)
{
  return getFS()->release(path, fi);
}

auto rt11_ftruncate(const char *path, off_t size, struct fuse_file_info *fi) -> int
{
  return getFS()->ftruncate(path, size, fi);
}

auto rt11_read(const char *path, char *buf, size_t count, off_t offset, struct fuse_file_info *fi)
{
  return getFS()->read(path, buf, count, offset, fi);
}

auto rt11_write(const char *path, const char *buf, size_t count, off_t offset, struct fuse_file_info *fi)
{
  return getFS()->write(path, buf, count, offset, fi);
}

auto rt11_fsync(const char *path, int isdatasync, struct fuse_file_info *fi)
{
  return getFS()->fsync(path, isdatasync, fi);
}

auto build_oper(struct fuse_operations *oper)
{
  add_unimpl(oper);

  oper->getattr = &rt11_getattr;
  oper->fgetattr = &rt11_fgetattr;
  oper->statfs = &rt11_statfs;
  oper->chmod = &rt11_chmod;
  oper->unlink = &rt11_unlink;
  oper->rename = &rt11_rename;
  oper->opendir = &rt11_opendir;
  oper->releasedir = &rt11_releasedir;
  oper->readdir = &rt11_readdir;
  oper->open = &rt11_open;
  oper->release = &rt11_release;
  oper->ftruncate = &rt11_ftruncate;
  oper->read = &rt11_read;
  oper->write = &rt11_write;
  oper->fsync = &rt11_fsync;
}

auto usage(const string &program)
{
  cerr << "usage: " << program << " disk-image mountpoint" << endl;
  exit(1);
}

struct fuse_opt rt11_opts[] =
{
  { "-i %s", offsetof(struct rt11_config, image), 0 },
  { "-d",    offsetof(struct rt11_config, listdir), 1},
  FUSE_OPT_END,
};

}

auto main(int argc, char *argv[]) -> int
{
  int exitcode;

  struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
  struct fuse_operations rt11_oper;
  struct rt11_config config;

  memset(&config, 0, sizeof(config));

  if (fuse_opt_parse(&args, &config, rt11_opts, NULL) == -1) {
    usage(argv[0]);
  }

  if (config.image == NULL) {
    cerr << argv[0] << ": must specify an image to mount" << endl;
    usage(argv[0]);
  }

  // make FUSE responsible for enforcing permission bits
  fuse_opt_add_arg(&args, "-odefault_permissions");

  // the file system isn't thread safe; make FUSE serialize requests
  // (it isn't likely that perf will be enough of an issues that this will ever matter)
  fuse_opt_add_arg(&args, "-s");

  FileSystem fs {config.image};

  if (config.listdir) {
    fs.lsdir();
    return 0;
  }

  build_oper(&rt11_oper);
  exitcode = fuse_main(args.argc, args.argv, &rt11_oper, &fs);

  fuse_opt_free_args(&args);
  return exitcode;
}<|endoftext|>


<commit_before>#include <eosio/trace_api/store_provider.hpp>

#include <fc/variant_object.hpp>
#include <fc/crypto/base64.hpp>

namespace {
      static constexpr uint32_t _current_version = 1;
      static constexpr const char* _trace_prefix = "trace_";
      static constexpr const char* _trace_index_prefix = "trace_index_";
      static constexpr const char* _trace_ext = ".log";
      static constexpr uint _max_filename_size = std::char_traits<char>::length(_trace_index_prefix) + 10 + 1 + 10 + std::char_traits<char>::length(_trace_ext) + 1; // "trace_index_" + 10-digits + '-' + 10-digits + ".log" + null-char
}

namespace eosio::trace_api {
   namespace bfs = boost::filesystem;
   store_provider::store_provider(const bfs::path& slice_dir, uint32_t width)
   : _slice_directory(slice_dir, width) {
   }

   void store_provider::append(const block_trace_v0& bt) {
      fc::cfile trace;
      fc::cfile index;
      find_or_create_slice_pair(bt.number, true, trace, index);
      // storing as static_variant to allow adding other data types to the trace file in the future
      const uint64_t offset = append_store(data_log_entry { bt }, trace);

      auto be = metadata_log_entry { block_entry_v0 { .id = bt.id, .number = bt.number, .offset = offset }};
      append_store(be, index);
   }

   void store_provider::append_lib(uint32_t lib) {
      fc::cfile index;
      const uint32_t slice_number = _slice_directory.slice_number(lib);
      _slice_directory.find_or_create_index_slice(slice_number, true, index);
      auto le = metadata_log_entry { lib_entry_v0 { .lib = lib }};
      append_store(le, index);
   }

   get_block_t store_provider::get_block(uint32_t block_height, const yield_function& yield) {
      std::optional<uint64_t> trace_offset;
      bool irreversible = false;
      uint64_t offset = scan_metadata_log_from(block_height, 0, [&block_height, &trace_offset, &irreversible](const metadata_log_entry& e) -> bool {
         if (e.contains<block_entry_v0>()) {
            const auto& block = e.get<block_entry_v0>();
            if (block.number == block_height) {
               trace_offset = block.offset;
            }
         } else if (e.contains<lib_entry_v0>()) {
            auto lib = e.get<lib_entry_v0>().lib;
            if (lib >= block_height) {
               irreversible = true;
               return false;
            }
         }
         return true;
      }, yield);
      if (!trace_offset) {
         return get_block_t{};
      }
      std::optional<data_log_entry> entry = read_data_log(block_height, *trace_offset);
      if (!entry) {
         return get_block_t{};
      }
      const auto bt = entry->get<block_trace_v0>();
      return std::make_tuple( bt, irreversible );
   }

   void store_provider::find_or_create_slice_pair(uint32_t block_height, bool append, fc::cfile& trace, fc::cfile& index) {
      const uint32_t slice_number = _slice_directory.slice_number(block_height);
      const bool trace_found = _slice_directory.find_or_create_trace_slice(slice_number, append, trace);
      const bool index_found = _slice_directory.find_or_create_index_slice(slice_number, append, index);
      if (trace_found != index_found) {
         const std::string trace_status = trace_found ? "existing" : "new";
         const std::string index_status = index_found ? "existing" : "new";
         elog("Trace file is ${ts}, but it's metadata file is ${is}. This means the files are not consistent.", ("ts", trace_status)("is", index_status));
      }
   }

   slice_directory::slice_directory(const bfs::path& slice_dir, uint32_t width)
   : _slice_dir(slice_dir), _width(width) {
      if (!exists(_slice_dir))
         throw path_does_not_exist("The provided path does not exist: " + _slice_dir.generic_string());
   }

   bool slice_directory::find_or_create_index_slice(uint32_t slice_number, bool append, fc::cfile& index_file) const {
      const bool found = find_index_slice(slice_number, append, index_file);
      if( !found ) {
         create_new_index_slice_file(index_file);
      }
      return found;
   }

   bool slice_directory::find_index_slice(uint32_t slice_number, bool append, fc::cfile& index_file) const {
      if( !find_slice(_trace_index_prefix, slice_number, index_file) ) {
         return false;
      }

      validate_existing_index_slice_file(index_file, append);
      return true;
   }

   void slice_directory::create_new_index_slice_file(fc::cfile& index_file) const {
      index_file.open(fc::cfile::create_or_update_rw_mode);
      index_header h { .version = _current_version };
      append_store(h, index_file);
   }

   void slice_directory::validate_existing_index_slice_file(fc::cfile& index_file, bool append) const {
      const auto header = extract_store<index_header>(index_file);
      if (header.version != _current_version) {
         throw old_slice_version("Old slice file with version: " + std::to_string(header.version) +
                                 " is in directory, only supporting version: " + std::to_string(_current_version));
      }
      if( append ) {
         index_file.seek_end(0);
      }
   }

   bool slice_directory::find_or_create_trace_slice(uint32_t slice_number, bool append, fc::cfile& trace_file) const {
      const bool found = find_trace_slice(slice_number, append, trace_file);

      if( !found ) {
         trace_file.open(fc::cfile::create_or_update_rw_mode);
      }
      else if( append ) {
         trace_file.seek_end(0);
      }

      return found;
   }

   bool slice_directory::find_trace_slice(uint32_t slice_number, bool append, fc::cfile& trace_file) const {
      const bool found = find_slice(_trace_prefix, slice_number, trace_file);

      if( !found ) {
         return false;
      }

      if( append ) {
         trace_file.seek_end(0);
      }
      return true;
   }

   bool slice_directory::find_slice(const char* slice_prefix, uint32_t slice_number, fc::cfile& slice_file) const {
      char filename[_max_filename_size] = {};
      const uint32_t slice_start = slice_number * _width;
      const int size_written = snprintf(filename, _max_filename_size, "%s%010d-%010d%s", slice_prefix, slice_start, (slice_start + _width), _trace_ext);
      // assert that _max_filename_size is correct
      if ( size_written >= _max_filename_size ) {
         const std::string max_size_str = std::to_string(_max_filename_size - 1); // dropping null character from size
         const std::string size_written_str = std::to_string(size_written);
         throw std::runtime_error("Could not write the complete filename.  Anticipated the max filename characters to be: " +
            max_size_str + " or less, but wrote: " + size_written_str + " characters.  This is likely because the file "
            "format was changed and the code was not updated accordingly. Filename created: " + filename);
      }
      const path slice_path = _slice_dir / filename;
      slice_file.set_file_path(slice_path);
      if( !exists(slice_path)) {
         return false;
      }

      slice_file.open(fc::cfile::create_or_update_rw_mode);
      return true;
   }
}
<commit_msg>Changed to creating the slice diretories if it doesn't exist.<commit_after>#include <eosio/trace_api/store_provider.hpp>

#include <fc/variant_object.hpp>
#include <fc/crypto/base64.hpp>

namespace {
      static constexpr uint32_t _current_version = 1;
      static constexpr const char* _trace_prefix = "trace_";
      static constexpr const char* _trace_index_prefix = "trace_index_";
      static constexpr const char* _trace_ext = ".log";
      static constexpr uint _max_filename_size = std::char_traits<char>::length(_trace_index_prefix) + 10 + 1 + 10 + std::char_traits<char>::length(_trace_ext) + 1; // "trace_index_" + 10-digits + '-' + 10-digits + ".log" + null-char
}

namespace eosio::trace_api {
   namespace bfs = boost::filesystem;
   store_provider::store_provider(const bfs::path& slice_dir, uint32_t width)
   : _slice_directory(slice_dir, width) {
   }

   void store_provider::append(const block_trace_v0& bt) {
      fc::cfile trace;
      fc::cfile index;
      find_or_create_slice_pair(bt.number, true, trace, index);
      // storing as static_variant to allow adding other data types to the trace file in the future
      const uint64_t offset = append_store(data_log_entry { bt }, trace);

      auto be = metadata_log_entry { block_entry_v0 { .id = bt.id, .number = bt.number, .offset = offset }};
      append_store(be, index);
   }

   void store_provider::append_lib(uint32_t lib) {
      fc::cfile index;
      const uint32_t slice_number = _slice_directory.slice_number(lib);
      _slice_directory.find_or_create_index_slice(slice_number, true, index);
      auto le = metadata_log_entry { lib_entry_v0 { .lib = lib }};
      append_store(le, index);
   }

   get_block_t store_provider::get_block(uint32_t block_height, const yield_function& yield) {
      std::optional<uint64_t> trace_offset;
      bool irreversible = false;
      uint64_t offset = scan_metadata_log_from(block_height, 0, [&block_height, &trace_offset, &irreversible](const metadata_log_entry& e) -> bool {
         if (e.contains<block_entry_v0>()) {
            const auto& block = e.get<block_entry_v0>();
            if (block.number == block_height) {
               trace_offset = block.offset;
            }
         } else if (e.contains<lib_entry_v0>()) {
            auto lib = e.get<lib_entry_v0>().lib;
            if (lib >= block_height) {
               irreversible = true;
               return false;
            }
         }
         return true;
      }, yield);
      if (!trace_offset) {
         return get_block_t{};
      }
      std::optional<data_log_entry> entry = read_data_log(block_height, *trace_offset);
      if (!entry) {
         return get_block_t{};
      }
      const auto bt = entry->get<block_trace_v0>();
      return std::make_tuple( bt, irreversible );
   }

   void store_provider::find_or_create_slice_pair(uint32_t block_height, bool append, fc::cfile& trace, fc::cfile& index) {
      const uint32_t slice_number = _slice_directory.slice_number(block_height);
      const bool trace_found = _slice_directory.find_or_create_trace_slice(slice_number, append, trace);
      const bool index_found = _slice_directory.find_or_create_index_slice(slice_number, append, index);
      if (trace_found != index_found) {
         const std::string trace_status = trace_found ? "existing" : "new";
         const std::string index_status = index_found ? "existing" : "new";
         elog("Trace file is ${ts}, but it's metadata file is ${is}. This means the files are not consistent.", ("ts", trace_status)("is", index_status));
      }
   }

   slice_directory::slice_directory(const bfs::path& slice_dir, uint32_t width)
   : _slice_dir(slice_dir), _width(width) {
      if (!exists(_slice_dir)) {
         bfs::create_directories(slice_dir);
      }
   }

   bool slice_directory::find_or_create_index_slice(uint32_t slice_number, bool append, fc::cfile& index_file) const {
      const bool found = find_index_slice(slice_number, append, index_file);
      if( !found ) {
         create_new_index_slice_file(index_file);
      }
      return found;
   }

   bool slice_directory::find_index_slice(uint32_t slice_number, bool append, fc::cfile& index_file) const {
      if( !find_slice(_trace_index_prefix, slice_number, index_file) ) {
         return false;
      }

      validate_existing_index_slice_file(index_file, append);
      return true;
   }

   void slice_directory::create_new_index_slice_file(fc::cfile& index_file) const {
      index_file.open(fc::cfile::create_or_update_rw_mode);
      index_header h { .version = _current_version };
      append_store(h, index_file);
   }

   void slice_directory::validate_existing_index_slice_file(fc::cfile& index_file, bool append) const {
      const auto header = extract_store<index_header>(index_file);
      if (header.version != _current_version) {
         throw old_slice_version("Old slice file with version: " + std::to_string(header.version) +
                                 " is in directory, only supporting version: " + std::to_string(_current_version));
      }
      if( append ) {
         index_file.seek_end(0);
      }
   }

   bool slice_directory::find_or_create_trace_slice(uint32_t slice_number, bool append, fc::cfile& trace_file) const {
      const bool found = find_trace_slice(slice_number, append, trace_file);

      if( !found ) {
         trace_file.open(fc::cfile::create_or_update_rw_mode);
      }
      else if( append ) {
         trace_file.seek_end(0);
      }

      return found;
   }

   bool slice_directory::find_trace_slice(uint32_t slice_number, bool append, fc::cfile& trace_file) const {
      const bool found = find_slice(_trace_prefix, slice_number, trace_file);

      if( !found ) {
         return false;
      }

      if( append ) {
         trace_file.seek_end(0);
      }
      return true;
   }

   bool slice_directory::find_slice(const char* slice_prefix, uint32_t slice_number, fc::cfile& slice_file) const {
      char filename[_max_filename_size] = {};
      const uint32_t slice_start = slice_number * _width;
      const int size_written = snprintf(filename, _max_filename_size, "%s%010d-%010d%s", slice_prefix, slice_start, (slice_start + _width), _trace_ext);
      // assert that _max_filename_size is correct
      if ( size_written >= _max_filename_size ) {
         const std::string max_size_str = std::to_string(_max_filename_size - 1); // dropping null character from size
         const std::string size_written_str = std::to_string(size_written);
         throw std::runtime_error("Could not write the complete filename.  Anticipated the max filename characters to be: " +
            max_size_str + " or less, but wrote: " + size_written_str + " characters.  This is likely because the file "
            "format was changed and the code was not updated accordingly. Filename created: " + filename);
      }
      const path slice_path = _slice_dir / filename;
      slice_file.set_file_path(slice_path);
      if( !exists(slice_path)) {
         return false;
      }

      slice_file.open(fc::cfile::create_or_update_rw_mode);
      return true;
   }
}
<|endoftext|>


<commit_before>#include "PacketCommunicator.h"

#include "MarshalingServices.h"
#include "PacketDumpFile.h"
#include "PacketTimestamp.h"
#include "PcapError.h"
#include "Pcap.h"

using namespace System;
using namespace System::Globalization;
using namespace System::Runtime::InteropServices;
using namespace System::Collections::ObjectModel;
using namespace System::Collections::Generic;
using namespace PcapDotNet::Packets;
using namespace PcapDotNet::Core;

PcapDataLink PacketCommunicator::DataLink::get()
{
    return PcapDataLink(pcap_datalink(_pcapDescriptor));
}

void PacketCommunicator::DataLink::set(PcapDataLink value)
{
    if (pcap_set_datalink(_pcapDescriptor, value.Value) == -1)
        throw BuildInvalidOperation("Failed setting datalink " + value.ToString());
}

ReadOnlyCollection<PcapDataLink>^ PacketCommunicator::SupportedDataLinks::get()
{
    int* dataLinks;
    int numDatalinks = pcap_list_datalinks(_pcapDescriptor, &dataLinks);
    if (numDatalinks == -1)
        throw BuildInvalidOperation("Failed getting supported datalinks");

    try
    {
        List<PcapDataLink>^ results = gcnew List<PcapDataLink>(numDatalinks);
        for (int i = 0; i != numDatalinks; ++i)
            results->Add(PcapDataLink(dataLinks[i]));
        return gcnew ReadOnlyCollection<PcapDataLink>(results);
    }
    finally
    {
		pcap_free_datalinks(dataLinks);
    }
}

int PacketCommunicator::SnapshotLength::get()
{
    return pcap_snapshot(_pcapDescriptor);
}

IpV4SocketAddress^ PacketCommunicator::IpV4Netmask::get()
{
    return _ipV4Netmask;
}

bool PacketCommunicator::IsFileSystemByteOrder::get()
{
    return (pcap_is_swapped(_pcapDescriptor) == 0);
}

int PacketCommunicator::FileMajorVersion::get()
{
    return pcap_major_version(_pcapDescriptor);
}

int PacketCommunicator::FileMinorVersion::get()
{
    return pcap_minor_version(_pcapDescriptor);
}

PacketCommunicatorMode PacketCommunicator::Mode::get()
{
    return _mode;
}

void PacketCommunicator::Mode::set(PacketCommunicatorMode value)
{
    if (pcap_setmode(_pcapDescriptor, safe_cast<int>(value)) < 0)
        throw BuildInvalidOperation("Error setting mode " + value.ToString());
    _mode = value;
}

bool PacketCommunicator::NonBlocking::get()
{
    char errorBuffer[PCAP_ERRBUF_SIZE];
    int nonBlockValue = pcap_getnonblock(_pcapDescriptor, errorBuffer);
    if (nonBlockValue == -1)
        throw BuildInvalidOperation("Error getting NonBlocking value");
    return nonBlockValue != 0;
}

void PacketCommunicator::NonBlocking::set(bool value)
{
    char errorBuffer[PCAP_ERRBUF_SIZE];
    if (pcap_setnonblock(_pcapDescriptor, value, errorBuffer) != 0)
        throw BuildInvalidOperation("Error setting NonBlocking to " + value.ToString());
}

void PacketCommunicator::SetKernelBufferSize(int size)
{
    if (pcap_setbuff(_pcapDescriptor, size) != 0)
        throw BuildInvalidOperation("Error setting kernel buffer size to " + size.ToString(CultureInfo::InvariantCulture));
}

void PacketCommunicator::SetKernelMinimumBytesToCopy(int size)
{
    if (pcap_setmintocopy(_pcapDescriptor, size) != 0)
        throw BuildInvalidOperation("Error setting kernel minimum bytes to copy to " + size.ToString(CultureInfo::InvariantCulture));
}

void PacketCommunicator::SetSamplingMethod(SamplingMethod^ method)
{
	if (method == nullptr)
		throw gcnew ArgumentNullException("method");

	pcap_samp* pcapSamplingMethod = pcap_setsampling(_pcapDescriptor);
    pcapSamplingMethod->method = method->Method;
    pcapSamplingMethod->value = method->Value;
}

PacketCommunicatorReceiveResult PacketCommunicator::ReceivePacket([Out] Packet^% packet)
{
    AssertMode(PacketCommunicatorMode::Capture);

    pcap_pkthdr* packetHeader;
    const unsigned char* packetData;
    PacketCommunicatorReceiveResult result = RunPcapNextEx(&packetHeader, &packetData);

    if (result != PacketCommunicatorReceiveResult::Ok)
    {
        packet = nullptr;
        return result;
    }

    packet = CreatePacket(*packetHeader, packetData, DataLink);
    return result;
}

PacketCommunicatorReceiveResult PacketCommunicator::ReceiveSomePackets([Out] int% countGot, int maxPackets, HandlePacket^ callBack)
{
    AssertMode(PacketCommunicatorMode::Capture);

    PacketHandler^ packetHandler = gcnew PacketHandler(callBack, DataLink);
    HandlerDelegate^ packetHandlerDelegate = gcnew HandlerDelegate(packetHandler, &PacketHandler::Handle);
    pcap_handler functionPointer = (pcap_handler)Marshal::GetFunctionPointerForDelegate(packetHandlerDelegate).ToPointer();

    countGot = pcap_dispatch(_pcapDescriptor,
                             maxPackets,
                             functionPointer,
                             NULL);
    GC::KeepAlive(packetHandlerDelegate);

    switch (countGot)
    {
    case -2:
        countGot = 0;
        return PacketCommunicatorReceiveResult::BreakLoop;
    case -1:
        throw BuildInvalidOperation("Failed reading from device");
    case 0:
        if (packetHandler->PacketCounter != 0)
        {
            countGot = packetHandler->PacketCounter;
            return PacketCommunicatorReceiveResult::Eof;
        }
    }

    return PacketCommunicatorReceiveResult::Ok;
}

PacketCommunicatorReceiveResult PacketCommunicator::ReceivePackets(int count, HandlePacket^ callback)
{
    AssertMode(PacketCommunicatorMode::Capture);

    PacketHandler^ packetHandler = gcnew PacketHandler(callback, DataLink);
    HandlerDelegate^ packetHandlerDelegate = gcnew HandlerDelegate(packetHandler, &PacketHandler::Handle);
    pcap_handler functionPointer = (pcap_handler)Marshal::GetFunctionPointerForDelegate(packetHandlerDelegate).ToPointer();

    int result = pcap_loop(_pcapDescriptor, count, functionPointer, NULL);
    GC::KeepAlive(packetHandlerDelegate);

    switch (result)
    {
    case -2:
        return PacketCommunicatorReceiveResult::BreakLoop;
    case -1:
        throw BuildInvalidOperation("Failed reading from device");
    case 0:
        if (packetHandler->PacketCounter != count)
            return PacketCommunicatorReceiveResult::Eof;
    }

    return PacketCommunicatorReceiveResult::Ok;
}

PacketCommunicatorReceiveResult PacketCommunicator::ReceiveStatistics([Out] PacketSampleStatistics^% statistics)
{
    AssertMode(PacketCommunicatorMode::Statistics);

    pcap_pkthdr* packetHeader;
    const unsigned char* packetData;
    PacketCommunicatorReceiveResult result = RunPcapNextEx(&packetHeader, &packetData);

    if (result != PacketCommunicatorReceiveResult::Ok)
        throw gcnew InvalidOperationException("Got result " + result.ToString() + " in statistics mode");

    statistics = gcnew PacketSampleStatistics(*packetHeader, packetData);

    return result;
}

PacketCommunicatorReceiveResult PacketCommunicator::ReceiveStatistics(int count, HandleStatistics^ callBack)
{
    AssertMode(PacketCommunicatorMode::Statistics);

    StatisticsHandler^ statisticsHandler = gcnew StatisticsHandler(callBack);
    HandlerDelegate^ statisticsHandlerDelegate = gcnew HandlerDelegate(statisticsHandler, &StatisticsHandler::Handle);
    pcap_handler functionPointer = (pcap_handler)Marshal::GetFunctionPointerForDelegate(statisticsHandlerDelegate).ToPointer();

    int result = pcap_loop(_pcapDescriptor, count, functionPointer, NULL);
    GC::KeepAlive(statisticsHandlerDelegate);

    if (result == -1)
        throw BuildInvalidOperation("Failed reading from device");
    if (result == -2)
        return PacketCommunicatorReceiveResult::BreakLoop;
    return PacketCommunicatorReceiveResult::Ok;
}

void PacketCommunicator::Break()
{
    pcap_breakloop(_pcapDescriptor);
}

void PacketCommunicator::SendPacket(Packet^ packet)
{
	if (packet == nullptr)
		throw gcnew ArgumentNullException("packet");

	if (packet->Length == 0)
        return;
    pin_ptr<Byte> unamangedPacketBytes = &packet->Buffer[0];
    if (pcap_sendpacket(_pcapDescriptor, unamangedPacketBytes, packet->Length) != 0)
        throw BuildInvalidOperation("Failed writing to device");
}

BerkeleyPacketFilter^ PacketCommunicator::CreateFilter(String^ filterValue)
{
    return gcnew BerkeleyPacketFilter(_pcapDescriptor, filterValue, _ipV4Netmask);
}

void PacketCommunicator::SetFilter(BerkeleyPacketFilter^ filter)
{
	if (filter == nullptr)
		throw gcnew ArgumentNullException("filter");

	filter->SetFilter(_pcapDescriptor);
}

void PacketCommunicator::SetFilter(String^ filterValue)
{
    BerkeleyPacketFilter^ filter = CreateFilter(filterValue);
    try
    {
        SetFilter(filter);
    }
    finally
    {
        filter->~BerkeleyPacketFilter();
    }
}

PacketDumpFile^ PacketCommunicator::OpenDump(System::String^ fileName)
{
    return gcnew PacketDumpFile(_pcapDescriptor, fileName);
}

PacketCommunicator::~PacketCommunicator()
{
    pcap_close(_pcapDescriptor);
}

// Internal

PacketCommunicator::PacketCommunicator(pcap_t* pcapDescriptor, SocketAddress^ netmask)
    : _pcapDescriptor(pcapDescriptor), _ipV4Netmask(dynamic_cast<IpV4SocketAddress^>(netmask))
{
}

// Protected

pcap_t* PacketCommunicator::PcapDescriptor::get()
{
    return _pcapDescriptor;
}

InvalidOperationException^ PacketCommunicator::BuildInvalidOperation(System::String^ errorMessage)
{
    return PcapError::BuildInvalidOperation(errorMessage, _pcapDescriptor);
}

// Private

// static
Packet^ PacketCommunicator::CreatePacket(const pcap_pkthdr& packetHeader, const unsigned char* packetData, IDataLink^ dataLink)
{
    DateTime timestamp;
    PacketTimestamp::PcapTimestampToDateTime(packetHeader.ts, timestamp);

    array<Byte>^ managedPacketData = MarshalingServices::UnamangedToManagedByteArray(packetData, 0, packetHeader.caplen);
    return gcnew Packet(managedPacketData, timestamp, dataLink);
}

PacketCommunicatorReceiveResult PacketCommunicator::RunPcapNextEx(pcap_pkthdr** packetHeader, const unsigned char** packetData)
{
    int result = pcap_next_ex(_pcapDescriptor, packetHeader, packetData);
    switch (result)
    {
    case -2:
        return PacketCommunicatorReceiveResult::Eof;
    case -1:
        throw PcapError::BuildInvalidOperation("Failed reading from device", _pcapDescriptor);
    case 0:
        return PacketCommunicatorReceiveResult::Timeout;
    case 1:
        return PacketCommunicatorReceiveResult::Ok;
    default:
        throw gcnew InvalidOperationException("Result value " + result.ToString(CultureInfo::InvariantCulture) + " is undefined");
    }
}

void PacketCommunicator::AssertMode(PacketCommunicatorMode mode)
{
    if (Mode != mode)
        throw gcnew InvalidOperationException("Wrong Mode. Must be in mode " + mode.ToString() + " and not in mode " + Mode.ToString());
}

void PacketCommunicator::PacketHandler::Handle(unsigned char *, const struct pcap_pkthdr *packetHeader, const unsigned char *packetData)
{
    ++_packetCounter;
    _callback->Invoke(CreatePacket(*packetHeader, packetData, _dataLink));
}

int PacketCommunicator::PacketHandler::PacketCounter::get()
{
    return _packetCounter;
}

void PacketCommunicator::StatisticsHandler::Handle(unsigned char *, const struct pcap_pkthdr *packetHeader, const unsigned char *packetData)
{
    _callback->Invoke(gcnew PacketSampleStatistics(*packetHeader, packetData));
}<commit_msg>Add packet length to the error message when failing writing packet to a device in SendPacket().<commit_after>#include "PacketCommunicator.h"

#include "MarshalingServices.h"
#include "PacketDumpFile.h"
#include "PacketTimestamp.h"
#include "PcapError.h"
#include "Pcap.h"

using namespace System;
using namespace System::Globalization;
using namespace System::Runtime::InteropServices;
using namespace System::Collections::ObjectModel;
using namespace System::Collections::Generic;
using namespace PcapDotNet::Packets;
using namespace PcapDotNet::Core;

PcapDataLink PacketCommunicator::DataLink::get()
{
    return PcapDataLink(pcap_datalink(_pcapDescriptor));
}

void PacketCommunicator::DataLink::set(PcapDataLink value)
{
    if (pcap_set_datalink(_pcapDescriptor, value.Value) == -1)
        throw BuildInvalidOperation("Failed setting datalink " + value.ToString());
}

ReadOnlyCollection<PcapDataLink>^ PacketCommunicator::SupportedDataLinks::get()
{
    int* dataLinks;
    int numDatalinks = pcap_list_datalinks(_pcapDescriptor, &dataLinks);
    if (numDatalinks == -1)
        throw BuildInvalidOperation("Failed getting supported datalinks");

    try
    {
        List<PcapDataLink>^ results = gcnew List<PcapDataLink>(numDatalinks);
        for (int i = 0; i != numDatalinks; ++i)
            results->Add(PcapDataLink(dataLinks[i]));
        return gcnew ReadOnlyCollection<PcapDataLink>(results);
    }
    finally
    {
		pcap_free_datalinks(dataLinks);
    }
}

int PacketCommunicator::SnapshotLength::get()
{
    return pcap_snapshot(_pcapDescriptor);
}

IpV4SocketAddress^ PacketCommunicator::IpV4Netmask::get()
{
    return _ipV4Netmask;
}

bool PacketCommunicator::IsFileSystemByteOrder::get()
{
    return (pcap_is_swapped(_pcapDescriptor) == 0);
}

int PacketCommunicator::FileMajorVersion::get()
{
    return pcap_major_version(_pcapDescriptor);
}

int PacketCommunicator::FileMinorVersion::get()
{
    return pcap_minor_version(_pcapDescriptor);
}

PacketCommunicatorMode PacketCommunicator::Mode::get()
{
    return _mode;
}

void PacketCommunicator::Mode::set(PacketCommunicatorMode value)
{
    if (pcap_setmode(_pcapDescriptor, safe_cast<int>(value)) < 0)
        throw BuildInvalidOperation("Error setting mode " + value.ToString());
    _mode = value;
}

bool PacketCommunicator::NonBlocking::get()
{
    char errorBuffer[PCAP_ERRBUF_SIZE];
    int nonBlockValue = pcap_getnonblock(_pcapDescriptor, errorBuffer);
    if (nonBlockValue == -1)
        throw BuildInvalidOperation("Error getting NonBlocking value");
    return nonBlockValue != 0;
}

void PacketCommunicator::NonBlocking::set(bool value)
{
    char errorBuffer[PCAP_ERRBUF_SIZE];
    if (pcap_setnonblock(_pcapDescriptor, value, errorBuffer) != 0)
        throw BuildInvalidOperation("Error setting NonBlocking to " + value.ToString());
}

void PacketCommunicator::SetKernelBufferSize(int size)
{
    if (pcap_setbuff(_pcapDescriptor, size) != 0)
        throw BuildInvalidOperation("Error setting kernel buffer size to " + size.ToString(CultureInfo::InvariantCulture));
}

void PacketCommunicator::SetKernelMinimumBytesToCopy(int size)
{
    if (pcap_setmintocopy(_pcapDescriptor, size) != 0)
        throw BuildInvalidOperation("Error setting kernel minimum bytes to copy to " + size.ToString(CultureInfo::InvariantCulture));
}

void PacketCommunicator::SetSamplingMethod(SamplingMethod^ method)
{
	if (method == nullptr)
		throw gcnew ArgumentNullException("method");

	pcap_samp* pcapSamplingMethod = pcap_setsampling(_pcapDescriptor);
    pcapSamplingMethod->method = method->Method;
    pcapSamplingMethod->value = method->Value;
}

PacketCommunicatorReceiveResult PacketCommunicator::ReceivePacket([Out] Packet^% packet)
{
    AssertMode(PacketCommunicatorMode::Capture);

    pcap_pkthdr* packetHeader;
    const unsigned char* packetData;
    PacketCommunicatorReceiveResult result = RunPcapNextEx(&packetHeader, &packetData);

    if (result != PacketCommunicatorReceiveResult::Ok)
    {
        packet = nullptr;
        return result;
    }

    packet = CreatePacket(*packetHeader, packetData, DataLink);
    return result;
}

PacketCommunicatorReceiveResult PacketCommunicator::ReceiveSomePackets([Out] int% countGot, int maxPackets, HandlePacket^ callBack)
{
    AssertMode(PacketCommunicatorMode::Capture);

    PacketHandler^ packetHandler = gcnew PacketHandler(callBack, DataLink);
    HandlerDelegate^ packetHandlerDelegate = gcnew HandlerDelegate(packetHandler, &PacketHandler::Handle);
    pcap_handler functionPointer = (pcap_handler)Marshal::GetFunctionPointerForDelegate(packetHandlerDelegate).ToPointer();

    countGot = pcap_dispatch(_pcapDescriptor,
                             maxPackets,
                             functionPointer,
                             NULL);
    GC::KeepAlive(packetHandlerDelegate);

    switch (countGot)
    {
    case -2:
        countGot = 0;
        return PacketCommunicatorReceiveResult::BreakLoop;
    case -1:
        throw BuildInvalidOperation("Failed reading from device");
    case 0:
        if (packetHandler->PacketCounter != 0)
        {
            countGot = packetHandler->PacketCounter;
            return PacketCommunicatorReceiveResult::Eof;
        }
    }

    return PacketCommunicatorReceiveResult::Ok;
}

PacketCommunicatorReceiveResult PacketCommunicator::ReceivePackets(int count, HandlePacket^ callback)
{
    AssertMode(PacketCommunicatorMode::Capture);

    PacketHandler^ packetHandler = gcnew PacketHandler(callback, DataLink);
    HandlerDelegate^ packetHandlerDelegate = gcnew HandlerDelegate(packetHandler, &PacketHandler::Handle);
    pcap_handler functionPointer = (pcap_handler)Marshal::GetFunctionPointerForDelegate(packetHandlerDelegate).ToPointer();

    int result = pcap_loop(_pcapDescriptor, count, functionPointer, NULL);
    GC::KeepAlive(packetHandlerDelegate);

    switch (result)
    {
    case -2:
        return PacketCommunicatorReceiveResult::BreakLoop;
    case -1:
        throw BuildInvalidOperation("Failed reading from device");
    case 0:
        if (packetHandler->PacketCounter != count)
            return PacketCommunicatorReceiveResult::Eof;
    }

    return PacketCommunicatorReceiveResult::Ok;
}

PacketCommunicatorReceiveResult PacketCommunicator::ReceiveStatistics([Out] PacketSampleStatistics^% statistics)
{
    AssertMode(PacketCommunicatorMode::Statistics);

    pcap_pkthdr* packetHeader;
    const unsigned char* packetData;
    PacketCommunicatorReceiveResult result = RunPcapNextEx(&packetHeader, &packetData);

    if (result != PacketCommunicatorReceiveResult::Ok)
        throw gcnew InvalidOperationException("Got result " + result.ToString() + " in statistics mode");

    statistics = gcnew PacketSampleStatistics(*packetHeader, packetData);

    return result;
}

PacketCommunicatorReceiveResult PacketCommunicator::ReceiveStatistics(int count, HandleStatistics^ callBack)
{
    AssertMode(PacketCommunicatorMode::Statistics);

    StatisticsHandler^ statisticsHandler = gcnew StatisticsHandler(callBack);
    HandlerDelegate^ statisticsHandlerDelegate = gcnew HandlerDelegate(statisticsHandler, &StatisticsHandler::Handle);
    pcap_handler functionPointer = (pcap_handler)Marshal::GetFunctionPointerForDelegate(statisticsHandlerDelegate).ToPointer();

    int result = pcap_loop(_pcapDescriptor, count, functionPointer, NULL);
    GC::KeepAlive(statisticsHandlerDelegate);

    if (result == -1)
        throw BuildInvalidOperation("Failed reading from device");
    if (result == -2)
        return PacketCommunicatorReceiveResult::BreakLoop;
    return PacketCommunicatorReceiveResult::Ok;
}

void PacketCommunicator::Break()
{
    pcap_breakloop(_pcapDescriptor);
}

void PacketCommunicator::SendPacket(Packet^ packet)
{
	if (packet == nullptr)
		throw gcnew ArgumentNullException("packet");

	if (packet->Length == 0)
        return;
    pin_ptr<Byte> unamangedPacketBytes = &packet->Buffer[0];
    if (pcap_sendpacket(_pcapDescriptor, unamangedPacketBytes, packet->Length) != 0)
        throw BuildInvalidOperation("Failed writing to device. Packet length: " + packet->Length);
}

BerkeleyPacketFilter^ PacketCommunicator::CreateFilter(String^ filterValue)
{
    return gcnew BerkeleyPacketFilter(_pcapDescriptor, filterValue, _ipV4Netmask);
}

void PacketCommunicator::SetFilter(BerkeleyPacketFilter^ filter)
{
	if (filter == nullptr)
		throw gcnew ArgumentNullException("filter");

	filter->SetFilter(_pcapDescriptor);
}

void PacketCommunicator::SetFilter(String^ filterValue)
{
    BerkeleyPacketFilter^ filter = CreateFilter(filterValue);
    try
    {
        SetFilter(filter);
    }
    finally
    {
        filter->~BerkeleyPacketFilter();
    }
}

PacketDumpFile^ PacketCommunicator::OpenDump(System::String^ fileName)
{
    return gcnew PacketDumpFile(_pcapDescriptor, fileName);
}

PacketCommunicator::~PacketCommunicator()
{
    pcap_close(_pcapDescriptor);
}

// Internal

PacketCommunicator::PacketCommunicator(pcap_t* pcapDescriptor, SocketAddress^ netmask)
    : _pcapDescriptor(pcapDescriptor), _ipV4Netmask(dynamic_cast<IpV4SocketAddress^>(netmask))
{
}

// Protected

pcap_t* PacketCommunicator::PcapDescriptor::get()
{
    return _pcapDescriptor;
}

InvalidOperationException^ PacketCommunicator::BuildInvalidOperation(System::String^ errorMessage)
{
    return PcapError::BuildInvalidOperation(errorMessage, _pcapDescriptor);
}

// Private

// static
Packet^ PacketCommunicator::CreatePacket(const pcap_pkthdr& packetHeader, const unsigned char* packetData, IDataLink^ dataLink)
{
    DateTime timestamp;
    PacketTimestamp::PcapTimestampToDateTime(packetHeader.ts, timestamp);

    array<Byte>^ managedPacketData = MarshalingServices::UnamangedToManagedByteArray(packetData, 0, packetHeader.caplen);
    return gcnew Packet(managedPacketData, timestamp, dataLink);
}

PacketCommunicatorReceiveResult PacketCommunicator::RunPcapNextEx(pcap_pkthdr** packetHeader, const unsigned char** packetData)
{
    int result = pcap_next_ex(_pcapDescriptor, packetHeader, packetData);
    switch (result)
    {
    case -2:
        return PacketCommunicatorReceiveResult::Eof;
    case -1:
        throw PcapError::BuildInvalidOperation("Failed reading from device", _pcapDescriptor);
    case 0:
        return PacketCommunicatorReceiveResult::Timeout;
    case 1:
        return PacketCommunicatorReceiveResult::Ok;
    default:
        throw gcnew InvalidOperationException("Result value " + result.ToString(CultureInfo::InvariantCulture) + " is undefined");
    }
}

void PacketCommunicator::AssertMode(PacketCommunicatorMode mode)
{
    if (Mode != mode)
        throw gcnew InvalidOperationException("Wrong Mode. Must be in mode " + mode.ToString() + " and not in mode " + Mode.ToString());
}

void PacketCommunicator::PacketHandler::Handle(unsigned char *, const struct pcap_pkthdr *packetHeader, const unsigned char *packetData)
{
    ++_packetCounter;
    _callback->Invoke(CreatePacket(*packetHeader, packetData, _dataLink));
}

int PacketCommunicator::PacketHandler::PacketCounter::get()
{
    return _packetCounter;
}

void PacketCommunicator::StatisticsHandler::Handle(unsigned char *, const struct pcap_pkthdr *packetHeader, const unsigned char *packetData)
{
    _callback->Invoke(gcnew PacketSampleStatistics(*packetHeader, packetData));
}<|endoftext|>


<commit_before>/*
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "c1cobfile.h"

std::string readpascalstring(std::istream &s) {
	uint16 size;
	uint8 a; s.read((char *)&a, 1);
	if (a == 255)
		size = read16(s);
	else
		size = a;

	boost::scoped_array<char> x(new char[size]);
	//char x[size];
	s.read(x.get(), size);
	return std::string(x.get(), size);
}

c1cobfile::c1cobfile(std::ifstream &s) {
	s >> std::noskipws;

	uint16 version = read16(s);

	// TODO: mph
	if (version != 1) {
		//QMessageBox::warning(this, tr("Failed to open"), tr("Version %1 is not supported").arg((int)version));
		return;
	}

	no_objects = read16(s);
	expire_month = read32(s);
	expire_day = read32(s);
	expire_year = read32(s);
	uint16 noscripts = read16(s);
	uint16 noimports = read16(s);
	no_objects_used = read16(s);
	uint16 reserved_zero = read16(s);
	assert(reserved_zero == 0);

	for (unsigned int i = 0; i < noscripts; i++)
		scripts.push_back(readpascalstring(s));
	for (unsigned int i = 0; i < noimports; i++)
		imports.push_back(readpascalstring(s));

	imagewidth = read32(s);
	imageheight = read32(s);
	uint16 secondimagewidth = read16(s);
	assert(imagewidth == secondimagewidth);
	imagedata.reset(new char[imagewidth * imageheight]);
	s.read(imagedata.get(), imagewidth * imageheight);
	name = readpascalstring(s);
}
<commit_msg>fix bad assert in c1cobfile<commit_after>/*
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "c1cobfile.h"

std::string readpascalstring(std::istream &s) {
	uint16 size;
	uint8 a; s.read((char *)&a, 1);
	if (a == 255)
		size = read16(s);
	else
		size = a;

	boost::scoped_array<char> x(new char[size]);
	//char x[size];
	s.read(x.get(), size);
	return std::string(x.get(), size);
}

c1cobfile::c1cobfile(std::ifstream &s) {
	s >> std::noskipws;

	uint16 version = read16(s);

	// TODO: mph
	if (version != 1) {
		//QMessageBox::warning(this, tr("Failed to open"), tr("Version %1 is not supported").arg((int)version));
		return;
	}

	no_objects = read16(s);
	expire_month = read32(s);
	expire_day = read32(s);
	expire_year = read32(s);
	uint16 noscripts = read16(s);
	uint16 noimports = read16(s);
	no_objects_used = read16(s);
	uint16 reserved_zero = read16(s);
	assert(reserved_zero == 0);

	for (unsigned int i = 0; i < noscripts; i++)
		scripts.push_back(readpascalstring(s));
	for (unsigned int i = 0; i < noimports; i++)
		imports.push_back(readpascalstring(s));

	imagewidth = read32(s);
	imageheight = read32(s);
	uint16 secondimagewidth = read16(s);
	if (imagewidth != secondimagewidth && secondimagewidth) // ABK- Egg Gender.cob has it zeroed
		std::cout << "ignoring COB secondimage width " << (int)secondimagewidth <<
			", using width " << imagewidth << std::endl;
	imagedata.reset(new char[imagewidth * imageheight]);
	s.read(imagedata.get(), imagewidth * imageheight);
	name = readpascalstring(s);
}
<|endoftext|>


<commit_before>#ifndef BTREE_PARALLEL_TRAVERSAL_HPP_
#define BTREE_PARALLEL_TRAVERSAL_HPP_

#include <utility>
#include <vector>

#include "utils.hpp"
#include <boost/shared_ptr.hpp>

#include "backfill_progress.hpp"
#include "buffer_cache/types.hpp"
#include "concurrency/access.hpp"
#include "concurrency/rwi_lock.hpp"
#include "concurrency/signal.hpp"
#include "containers/scoped.hpp"

struct btree_superblock_t;
class traversal_state_t;
class parent_releaser_t;
class btree_slice_t;
struct btree_key_t;
struct internal_node_t;
class superblock_t;

// HEY: Make this an abstract class, have two separate implementation
// classes for the "forced block id" case and the internal node case.
// (Hint: I don't really care.)
class ranged_block_ids_t {
public:
    ranged_block_ids_t(block_size_t bs, const internal_node_t *node,
                       const btree_key_t *left_exclusive_or_null,
                       const btree_key_t *right_inclusive_or_null,
                       int _level)
        : node_(bs.value()),
          left_exclusive_or_null_(left_exclusive_or_null),
          right_inclusive_or_null_(right_inclusive_or_null),
          level(_level)
    {
        memcpy(node_.get(), node, bs.value());
    }
    ranged_block_ids_t(block_id_t forced_block_id,
                       const btree_key_t *left_exclusive_or_null,
                       const btree_key_t *right_inclusive_or_null,
                       int _level)
        : node_(),
          forced_block_id_(forced_block_id),
          left_exclusive_or_null_(left_exclusive_or_null),
          right_inclusive_or_null_(right_inclusive_or_null),
          level(_level)
    { }

    int num_block_ids() const;
    void get_block_id_and_bounding_interval(int index,
                                            block_id_t *block_id_out,
                                            const btree_key_t **left_excl_bound_out,
                                            const btree_key_t **right_incl_bound_out) const;

    int get_level();

private:
    scoped_malloc_t<internal_node_t> node_;
    block_id_t forced_block_id_;
    const btree_key_t *left_exclusive_or_null_;
    const btree_key_t *right_inclusive_or_null_;
    int level;
};

class interesting_children_callback_t : public lock_in_line_callback_t {
public:
    // Call these function in filter_interesting_children.
    void receive_interesting_child(int child_index);
    void no_more_interesting_children();

    // internal
    void on_in_line();
    void decr_acquisition_countdown();

    interesting_children_callback_t(traversal_state_t *_state, parent_releaser_t *_releaser, int _level, const boost::shared_ptr<ranged_block_ids_t>& _ids_source)
        : state(_state), releaser(_releaser), level(_level), acquisition_countdown(1), ids_source(_ids_source) { }

private:
    traversal_state_t *state;
    parent_releaser_t *releaser;
    int level;
    int acquisition_countdown;
    boost::shared_ptr<ranged_block_ids_t> ids_source;

    DISABLE_COPYING(interesting_children_callback_t);
};

class parallel_traversal_progress_t;

struct btree_traversal_helper_t {
    btree_traversal_helper_t()
        : progress(NULL)
    { }

    //Before any of these other functions are called the helper gets a chance
    //to look at the stat block and possibly record some values of interest
    //Notice the values in the stat block do not reflect changes which are
    //still traversing the tree at the time this is called. Also notice that
    //this value may be null if the stat block has not been allocated yet and
    //this traversal is read only (which prohibits us from allocating it)
    virtual void read_stat_block(buf_lock_t *) { }

    // This is free to call mark_deleted.
    virtual void process_a_leaf(transaction_t *txn, buf_lock_t *leaf_node_buf,
                                const btree_key_t *left_exclusive_or_null,
                                const btree_key_t *right_inclusive_or_null,
                                int *population_change_out,
                                signal_t *interruptor) THROWS_ONLY(interrupted_exc_t) = 0;

    virtual void postprocess_internal_node(buf_lock_t *internal_node_buf) = 0;

    virtual void filter_interesting_children(transaction_t *txn, ranged_block_ids_t *ids_source, interesting_children_callback_t *cb) = 0;

    virtual access_t btree_superblock_mode() = 0;
    virtual access_t btree_node_mode() = 0;

    virtual ~btree_traversal_helper_t() { }

    parallel_traversal_progress_t *progress;
};

void btree_parallel_traversal(transaction_t *txn,
        superblock_t *superblock,
        btree_slice_t *slice,
        btree_traversal_helper_t *helper,
        signal_t *interruptor)
        THROWS_ONLY(interrupted_exc_t);

class parallel_traversal_progress_t : public traversal_progress_t {
public:
    parallel_traversal_progress_t()
        : height(-1), print_counter(0)
    { }

    enum action_t {
        LEARN,
        ACQUIRE,
        RELEASE
    };

    enum node_type_t {
        UNKNOWN,
        INTERNAL,
        LEAF
    };

    void inform(int level, action_t, node_type_t);

    progress_completion_fraction_t guess_completion() const;

private:
    std::vector<int> learned; //How many nodes at each level we believe exist
    std::vector<int> acquired; //How many nodes at each level we've acquired
    std::vector<int> released; //How many nodes at each level we've released

    int height; //The height we've learned the tree has. Or -1 if we're still unsure;

    int print_counter;

    DISABLE_COPYING(parallel_traversal_progress_t);
};

#endif  // BTREE_PARALLEL_TRAVERSAL_HPP_
<commit_msg>Cleaned up privacy of stuff in parallel_traversal.hpp.<commit_after>#ifndef BTREE_PARALLEL_TRAVERSAL_HPP_
#define BTREE_PARALLEL_TRAVERSAL_HPP_

#include <utility>
#include <vector>

#include "utils.hpp"
#include <boost/shared_ptr.hpp>

#include "backfill_progress.hpp"
#include "buffer_cache/types.hpp"
#include "concurrency/access.hpp"
#include "concurrency/rwi_lock.hpp"
#include "concurrency/signal.hpp"
#include "containers/scoped.hpp"

struct btree_superblock_t;
class traversal_state_t;
class parent_releaser_t;
class btree_slice_t;
struct btree_key_t;
struct internal_node_t;
class superblock_t;

// HEY: Make this an abstract class, have two separate implementation
// classes for the "forced block id" case and the internal node case.
// (Hint: I don't really care.)
class ranged_block_ids_t {
public:
    ranged_block_ids_t(block_size_t bs, const internal_node_t *node,
                       const btree_key_t *left_exclusive_or_null,
                       const btree_key_t *right_inclusive_or_null,
                       int _level)
        : node_(bs.value()),
          left_exclusive_or_null_(left_exclusive_or_null),
          right_inclusive_or_null_(right_inclusive_or_null),
          level(_level)
    {
        memcpy(node_.get(), node, bs.value());
    }
    ranged_block_ids_t(block_id_t forced_block_id,
                       const btree_key_t *left_exclusive_or_null,
                       const btree_key_t *right_inclusive_or_null,
                       int _level)
        : node_(),
          forced_block_id_(forced_block_id),
          left_exclusive_or_null_(left_exclusive_or_null),
          right_inclusive_or_null_(right_inclusive_or_null),
          level(_level)
    { }

    int num_block_ids() const;
    void get_block_id_and_bounding_interval(int index,
                                            block_id_t *block_id_out,
                                            const btree_key_t **left_excl_bound_out,
                                            const btree_key_t **right_incl_bound_out) const;

    int get_level();

private:
    scoped_malloc_t<internal_node_t> node_;
    block_id_t forced_block_id_;
    const btree_key_t *left_exclusive_or_null_;
    const btree_key_t *right_inclusive_or_null_;
    int level;

    DISABLE_COPYING(ranged_block_ids_t);
};

class interesting_children_callback_t : public lock_in_line_callback_t {
public:
    // Call these function in filter_interesting_children.
    void receive_interesting_child(int child_index);
    void no_more_interesting_children();

    interesting_children_callback_t(traversal_state_t *_state, parent_releaser_t *_releaser, int _level, const boost::shared_ptr<ranged_block_ids_t>& _ids_source)
        : state(_state), releaser(_releaser), level(_level), acquisition_countdown(1), ids_source(_ids_source) { }

private:
    void on_in_line();
    void decr_acquisition_countdown();

    traversal_state_t *state;
    parent_releaser_t *releaser;
    int level;
    int acquisition_countdown;
    boost::shared_ptr<ranged_block_ids_t> ids_source;

    DISABLE_COPYING(interesting_children_callback_t);
};

class parallel_traversal_progress_t;

struct btree_traversal_helper_t {
    btree_traversal_helper_t()
        : progress(NULL)
    { }

    //Before any of these other functions are called the helper gets a chance
    //to look at the stat block and possibly record some values of interest
    //Notice the values in the stat block do not reflect changes which are
    //still traversing the tree at the time this is called. Also notice that
    //this value may be null if the stat block has not been allocated yet and
    //this traversal is read only (which prohibits us from allocating it)
    virtual void read_stat_block(buf_lock_t *) { }

    // This is free to call mark_deleted.
    virtual void process_a_leaf(transaction_t *txn, buf_lock_t *leaf_node_buf,
                                const btree_key_t *left_exclusive_or_null,
                                const btree_key_t *right_inclusive_or_null,
                                int *population_change_out,
                                signal_t *interruptor) THROWS_ONLY(interrupted_exc_t) = 0;

    virtual void postprocess_internal_node(buf_lock_t *internal_node_buf) = 0;

    virtual void filter_interesting_children(transaction_t *txn, ranged_block_ids_t *ids_source, interesting_children_callback_t *cb) = 0;

    virtual access_t btree_superblock_mode() = 0;
    virtual access_t btree_node_mode() = 0;

    virtual ~btree_traversal_helper_t() { }

    parallel_traversal_progress_t *progress;
};

void btree_parallel_traversal(transaction_t *txn,
        superblock_t *superblock,
        btree_slice_t *slice,
        btree_traversal_helper_t *helper,
        signal_t *interruptor)
        THROWS_ONLY(interrupted_exc_t);

class parallel_traversal_progress_t : public traversal_progress_t {
public:
    parallel_traversal_progress_t()
        : height(-1), print_counter(0)
    { }

    enum action_t {
        LEARN,
        ACQUIRE,
        RELEASE
    };

    enum node_type_t {
        UNKNOWN,
        INTERNAL,
        LEAF
    };

    void inform(int level, action_t, node_type_t);

    progress_completion_fraction_t guess_completion() const;

private:
    std::vector<int> learned; //How many nodes at each level we believe exist
    std::vector<int> acquired; //How many nodes at each level we've acquired
    std::vector<int> released; //How many nodes at each level we've released

    int height; //The height we've learned the tree has. Or -1 if we're still unsure;

    int print_counter;

    DISABLE_COPYING(parallel_traversal_progress_t);
};

#endif  // BTREE_PARALLEL_TRAVERSAL_HPP_
<|endoftext|>