<commit_before>//===-- SparcV9TargetMachine.cpp - SparcV9 Target Machine Implementation --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Primary interface to machine description for the UltraSPARC.  Primarily just
// initializes machine-dependent parameters in class TargetMachine, and creates
// machine-dependent subclasses for classes such as TargetInstrInfo.
//
//===----------------------------------------------------------------------===//

#include "llvm/Function.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/CodeGen/InstrScheduling.h"
#include "llvm/CodeGen/IntrinsicLowering.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "MappingInfo.h"
#include "MachineFunctionInfo.h"
#include "MachineCodeForInstruction.h"
#include "SparcV9Internals.h"
#include "SparcV9TargetMachine.h"
#include "SparcV9BurgISel.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;

static const unsigned ImplicitRegUseList[] = { 0 }; /* not used yet */
// Build the MachineInstruction Description Array...
const TargetInstrDescriptor llvm::SparcV9MachineInstrDesc[] = {
#define I(ENUM, OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \
          NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS)             \
  { OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE,             \
          NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS, 0,          \
          ImplicitRegUseList, ImplicitRegUseList },
#include "SparcV9Instr.def"
};

//---------------------------------------------------------------------------
// Command line options to control choice of code generation passes.
//---------------------------------------------------------------------------

namespace llvm {
  bool EmitMappingInfo = false;
}

namespace {
  cl::opt<bool> DisableSched("disable-sched",
                             cl::desc("Disable local scheduling pass"));

  cl::opt<bool> DisablePeephole("disable-peephole",
                                cl::desc("Disable peephole optimization pass"));

  cl::opt<bool, true> EmitMappingInfoOpt("enable-maps",
                 cl::location(EmitMappingInfo),
                 cl::init(false),
                 cl::desc("Emit LLVM-to-MachineCode mapping info to assembly"));

  cl::opt<bool> DisableStrip("disable-strip",
                      cl::desc("Do not strip the LLVM bytecode in executable"));

  cl::opt<bool> EnableModSched("enable-ModSched", cl::desc("Enable modulo scheduling pass instead of local scheduling"));

  // Register the target.
  RegisterTarget<SparcV9TargetMachine> X("sparcv9", "  SPARC V9");
}

unsigned SparcV9TargetMachine::getJITMatchQuality() {
#if defined(__sparcv9)
  return 10;
#else
  return 0;
#endif
}

unsigned SparcV9TargetMachine::getModuleMatchQuality(const Module &M) {
  if (M.getEndianness()  == Module::BigEndian &&
      M.getPointerSize() == Module::Pointer64)
    return 10;                                   // Direct match
  else if (M.getEndianness() != Module::AnyEndianness ||
           M.getPointerSize() != Module::AnyPointerSize)
    return 0;                                    // Match for some other target

  return getJITMatchQuality()/2;
}

//===---------------------------------------------------------------------===//
// Code generation/destruction passes
//===---------------------------------------------------------------------===//

namespace {
  class ConstructMachineFunction : public FunctionPass {
    TargetMachine &Target;
  public:
    ConstructMachineFunction(TargetMachine &T) : Target(T) {}

    const char *getPassName() const {
      return "ConstructMachineFunction";
    }

    bool runOnFunction(Function &F) {
      MachineFunction::construct(&F, Target).getInfo<SparcV9FunctionInfo>()->CalculateArgSize();
      return false;
    }
  };

  struct DestroyMachineFunction : public FunctionPass {
    const char *getPassName() const { return "DestroyMachineFunction"; }

    static void freeMachineCode(Instruction &I) {
      MachineCodeForInstruction::destroy(&I);
    }

    bool runOnFunction(Function &F) {
      for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
        for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E; ++I)
          MachineCodeForInstruction::get(I).dropAllReferences();

      for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
        for_each(FI->begin(), FI->end(), freeMachineCode);

      MachineFunction::destruct(&F);
      return false;
    }
  };

  FunctionPass *createMachineCodeConstructionPass(TargetMachine &Target) {
    return new ConstructMachineFunction(Target);
  }
}

FunctionPass *llvm::createSparcV9MachineCodeDestructionPass() {
  return new DestroyMachineFunction();
}

SparcV9TargetMachine::SparcV9TargetMachine(const Module &M,
                                           IntrinsicLowering *il)
  : TargetMachine("UltraSparcV9-Native", il, false),
    schedInfo(*this),
    regInfo(*this),
    frameInfo(*this),
    jitInfo(*this) {
}

/// addPassesToEmitAssembly - This method controls the entire code generation
/// process for the ultra sparc.
///
bool
SparcV9TargetMachine::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out)
{
  // FIXME: Implement efficient support for garbage collection intrinsics.
  PM.add(createLowerGCPass());

  // Replace malloc and free instructions with library calls.
  PM.add(createLowerAllocationsPass());

  // FIXME: implement the switch instruction in the instruction selector.
  PM.add(createLowerSwitchPass());

  // FIXME: implement the invoke/unwind instructions!
  PM.add(createLowerInvokePass());

  // decompose multi-dimensional array references into single-dim refs
  PM.add(createDecomposeMultiDimRefsPass());

  // Lower LLVM code to the form expected by the SPARCv9 instruction selector.
  PM.add(createPreSelectionPass(*this));
  PM.add(createLowerSelectPass());

  // Run basic LLVM dataflow optimizations, to clean up after pre-selection.
  PM.add(createReassociatePass());
  PM.add(createLICMPass());
  PM.add(createGCSEPass());

  // If the user's trying to read the generated code, they'll need to see the
  // transformed input.
  if (PrintMachineCode)
    PM.add(new PrintModulePass());

  // Construct and initialize the MachineFunction object for this fn.
  PM.add(createMachineCodeConstructionPass(*this));

  // Insert empty stackslots in the stack frame of each function
  // so %fp+offset-8 and %fp+offset-16 are empty slots now!
  PM.add(createStackSlotsPass(*this));

  PM.add(createSparcV9BurgInstSelector(*this));

  if(PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "Before modulo scheduling:\n"));

  //Use ModuloScheduling if enabled, otherwise use local scheduling if not disabled.
  if(EnableModSched)
    PM.add(createModuloSchedulingPass(*this));
  else {
    if (!DisableSched)
      PM.add(createInstructionSchedulingWithSSAPass(*this));
  }

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "Before reg alloc:\n"));

  PM.add(getRegisterAllocator(*this));

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "After reg alloc:\n"));

  PM.add(createPrologEpilogInsertionPass());

  if (!DisablePeephole)
    PM.add(createPeepholeOptsPass(*this));

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "Final code:\n"));

  if (EmitMappingInfo) {
    PM.add(createInternalGlobalMapperPass());
    PM.add(getMappingInfoAsmPrinterPass(Out));
  }

  // Output assembly language to the .s file.  Assembly emission is split into
  // two parts: Function output and Global value output.  This is because
  // function output is pipelined with all of the rest of code generation stuff,
  // allowing machine code representations for functions to be free'd after the
  // function has been emitted.
  PM.add(createAsmPrinterPass(Out, *this));

  // Free machine-code IR which is no longer needed:
  PM.add(createSparcV9MachineCodeDestructionPass());

  // Emit bytecode to the assembly file into its special section next
  if (EmitMappingInfo) {
    // Strip all of the symbols from the bytecode so that it will be smaller...
    if (!DisableStrip)
      PM.add(createSymbolStrippingPass());
    PM.add(createBytecodeAsmPrinterPass(Out));
  }

  return false;
}

/// addPassesToJITCompile - This method controls the JIT method of code
/// generation for the UltraSparcV9.
///
void SparcV9JITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
  // FIXME: Implement efficient support for garbage collection intrinsics.
  PM.add(createLowerGCPass());

  // Replace malloc and free instructions with library calls.
  PM.add(createLowerAllocationsPass());

  // FIXME: implement the switch instruction in the instruction selector.
  PM.add(createLowerSwitchPass());

  // FIXME: implement the invoke/unwind instructions!
  PM.add(createLowerInvokePass());

  // decompose multi-dimensional array references into single-dim refs
  PM.add(createDecomposeMultiDimRefsPass());

  // Lower LLVM code to the form expected by the SPARCv9 instruction selector.
  PM.add(createPreSelectionPass(TM));
  PM.add(createLowerSelectPass());

  // Run basic LLVM dataflow optimizations, to clean up after pre-selection.
  PM.add(createReassociatePass());
  // FIXME: these passes crash the FunctionPassManager when being added...
  //PM.add(createLICMPass());
  //PM.add(createGCSEPass());

  // If the user's trying to read the generated code, they'll need to see the
  // transformed input.
  if (PrintMachineCode)
    PM.add(new PrintFunctionPass());

  // Construct and initialize the MachineFunction object for this fn.
  PM.add(createMachineCodeConstructionPass(TM));

  PM.add(createSparcV9BurgInstSelector(TM));

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "Before reg alloc:\n"));

  PM.add(getRegisterAllocator(TM));

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "After reg alloc:\n"));

  PM.add(createPrologEpilogInsertionPass());

  if (!DisablePeephole)
    PM.add(createPeepholeOptsPass(TM));

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "Final code:\n"));
}

<commit_msg>Fixed to fit in 80 columns.<commit_after>//===-- SparcV9TargetMachine.cpp - SparcV9 Target Machine Implementation --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Primary interface to machine description for the UltraSPARC.  Primarily just
// initializes machine-dependent parameters in class TargetMachine, and creates
// machine-dependent subclasses for classes such as TargetInstrInfo.
//
//===----------------------------------------------------------------------===//

#include "llvm/Function.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/CodeGen/InstrScheduling.h"
#include "llvm/CodeGen/IntrinsicLowering.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "MappingInfo.h"
#include "MachineFunctionInfo.h"
#include "MachineCodeForInstruction.h"
#include "SparcV9Internals.h"
#include "SparcV9TargetMachine.h"
#include "SparcV9BurgISel.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;

static const unsigned ImplicitRegUseList[] = { 0 }; /* not used yet */
// Build the MachineInstruction Description Array...
const TargetInstrDescriptor llvm::SparcV9MachineInstrDesc[] = {
#define I(ENUM, OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \
          NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS)             \
  { OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE,             \
          NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS, 0,          \
          ImplicitRegUseList, ImplicitRegUseList },
#include "SparcV9Instr.def"
};

//---------------------------------------------------------------------------
// Command line options to control choice of code generation passes.
//---------------------------------------------------------------------------

namespace llvm {
  bool EmitMappingInfo = false;
}

namespace {
  cl::opt<bool> DisableSched("disable-sched",
                             cl::desc("Disable local scheduling pass"));

  cl::opt<bool> DisablePeephole("disable-peephole",
                                cl::desc("Disable peephole optimization pass"));

  cl::opt<bool, true> EmitMappingInfoOpt("enable-maps",
                 cl::location(EmitMappingInfo),
                 cl::init(false),
                 cl::desc("Emit LLVM-to-MachineCode mapping info to assembly"));

  cl::opt<bool> DisableStrip("disable-strip",
                      cl::desc("Do not strip the LLVM bytecode in executable"));

  cl::opt<bool> EnableModSched("enable-ModSched",
	 cl::desc("Enable modulo scheduling pass instead of local scheduling"));

  // Register the target.
  RegisterTarget<SparcV9TargetMachine> X("sparcv9", "  SPARC V9");
}

unsigned SparcV9TargetMachine::getJITMatchQuality() {
#if defined(__sparcv9)
  return 10;
#else
  return 0;
#endif
}

unsigned SparcV9TargetMachine::getModuleMatchQuality(const Module &M) {
  if (M.getEndianness()  == Module::BigEndian &&
      M.getPointerSize() == Module::Pointer64)
    return 10;                                   // Direct match
  else if (M.getEndianness() != Module::AnyEndianness ||
           M.getPointerSize() != Module::AnyPointerSize)
    return 0;                                    // Match for some other target

  return getJITMatchQuality()/2;
}

//===---------------------------------------------------------------------===//
// Code generation/destruction passes
//===---------------------------------------------------------------------===//

namespace {
  class ConstructMachineFunction : public FunctionPass {
    TargetMachine &Target;
  public:
    ConstructMachineFunction(TargetMachine &T) : Target(T) {}

    const char *getPassName() const {
      return "ConstructMachineFunction";
    }

    bool runOnFunction(Function &F) {
      MachineFunction::construct(&F, Target).getInfo<SparcV9FunctionInfo>()->CalculateArgSize();
      return false;
    }
  };

  struct DestroyMachineFunction : public FunctionPass {
    const char *getPassName() const { return "DestroyMachineFunction"; }

    static void freeMachineCode(Instruction &I) {
      MachineCodeForInstruction::destroy(&I);
    }

    bool runOnFunction(Function &F) {
      for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
        for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E; ++I)
          MachineCodeForInstruction::get(I).dropAllReferences();

      for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
        for_each(FI->begin(), FI->end(), freeMachineCode);

      MachineFunction::destruct(&F);
      return false;
    }
  };

  FunctionPass *createMachineCodeConstructionPass(TargetMachine &Target) {
    return new ConstructMachineFunction(Target);
  }
}

FunctionPass *llvm::createSparcV9MachineCodeDestructionPass() {
  return new DestroyMachineFunction();
}

SparcV9TargetMachine::SparcV9TargetMachine(const Module &M,
                                           IntrinsicLowering *il)
  : TargetMachine("UltraSparcV9-Native", il, false),
    schedInfo(*this),
    regInfo(*this),
    frameInfo(*this),
    jitInfo(*this) {
}

/// addPassesToEmitAssembly - This method controls the entire code generation
/// process for the ultra sparc.
///
bool
SparcV9TargetMachine::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out)
{
  // FIXME: Implement efficient support for garbage collection intrinsics.
  PM.add(createLowerGCPass());

  // Replace malloc and free instructions with library calls.
  PM.add(createLowerAllocationsPass());

  // FIXME: implement the switch instruction in the instruction selector.
  PM.add(createLowerSwitchPass());

  // FIXME: implement the invoke/unwind instructions!
  PM.add(createLowerInvokePass());

  // decompose multi-dimensional array references into single-dim refs
  PM.add(createDecomposeMultiDimRefsPass());

  // Lower LLVM code to the form expected by the SPARCv9 instruction selector.
  PM.add(createPreSelectionPass(*this));
  PM.add(createLowerSelectPass());

  // Run basic LLVM dataflow optimizations, to clean up after pre-selection.
  PM.add(createReassociatePass());
  PM.add(createLICMPass());
  PM.add(createGCSEPass());

  // If the user's trying to read the generated code, they'll need to see the
  // transformed input.
  if (PrintMachineCode)
    PM.add(new PrintModulePass());

  // Construct and initialize the MachineFunction object for this fn.
  PM.add(createMachineCodeConstructionPass(*this));

  // Insert empty stackslots in the stack frame of each function
  // so %fp+offset-8 and %fp+offset-16 are empty slots now!
  PM.add(createStackSlotsPass(*this));

  PM.add(createSparcV9BurgInstSelector(*this));

  if(PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "Before modulo scheduling:\n"));

  //Use ModuloScheduling if enabled, otherwise use local scheduling if not disabled.
  if(EnableModSched)
    PM.add(createModuloSchedulingPass(*this));
  else {
    if (!DisableSched)
      PM.add(createInstructionSchedulingWithSSAPass(*this));
  }

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "Before reg alloc:\n"));

  PM.add(getRegisterAllocator(*this));

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "After reg alloc:\n"));

  PM.add(createPrologEpilogInsertionPass());

  if (!DisablePeephole)
    PM.add(createPeepholeOptsPass(*this));

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "Final code:\n"));

  if (EmitMappingInfo) {
    PM.add(createInternalGlobalMapperPass());
    PM.add(getMappingInfoAsmPrinterPass(Out));
  }

  // Output assembly language to the .s file.  Assembly emission is split into
  // two parts: Function output and Global value output.  This is because
  // function output is pipelined with all of the rest of code generation stuff,
  // allowing machine code representations for functions to be free'd after the
  // function has been emitted.
  PM.add(createAsmPrinterPass(Out, *this));

  // Free machine-code IR which is no longer needed:
  PM.add(createSparcV9MachineCodeDestructionPass());

  // Emit bytecode to the assembly file into its special section next
  if (EmitMappingInfo) {
    // Strip all of the symbols from the bytecode so that it will be smaller...
    if (!DisableStrip)
      PM.add(createSymbolStrippingPass());
    PM.add(createBytecodeAsmPrinterPass(Out));
  }

  return false;
}

/// addPassesToJITCompile - This method controls the JIT method of code
/// generation for the UltraSparcV9.
///
void SparcV9JITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
  // FIXME: Implement efficient support for garbage collection intrinsics.
  PM.add(createLowerGCPass());

  // Replace malloc and free instructions with library calls.
  PM.add(createLowerAllocationsPass());

  // FIXME: implement the switch instruction in the instruction selector.
  PM.add(createLowerSwitchPass());

  // FIXME: implement the invoke/unwind instructions!
  PM.add(createLowerInvokePass());

  // decompose multi-dimensional array references into single-dim refs
  PM.add(createDecomposeMultiDimRefsPass());

  // Lower LLVM code to the form expected by the SPARCv9 instruction selector.
  PM.add(createPreSelectionPass(TM));
  PM.add(createLowerSelectPass());

  // Run basic LLVM dataflow optimizations, to clean up after pre-selection.
  PM.add(createReassociatePass());
  // FIXME: these passes crash the FunctionPassManager when being added...
  //PM.add(createLICMPass());
  //PM.add(createGCSEPass());

  // If the user's trying to read the generated code, they'll need to see the
  // transformed input.
  if (PrintMachineCode)
    PM.add(new PrintFunctionPass());

  // Construct and initialize the MachineFunction object for this fn.
  PM.add(createMachineCodeConstructionPass(TM));

  PM.add(createSparcV9BurgInstSelector(TM));

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "Before reg alloc:\n"));

  PM.add(getRegisterAllocator(TM));

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "After reg alloc:\n"));

  PM.add(createPrologEpilogInsertionPass());

  if (!DisablePeephole)
    PM.add(createPeepholeOptsPass(TM));

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr, "Final code:\n"));
}

<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// class interface header
#include "cURLManager.h"

// common implementation headers
#include "bzfio.h"

bool                    cURLManager::inited      = false;
CURLM                  *cURLManager::multiHandle = NULL;
std::map<CURL*,
	 cURLManager*>  cURLManager::cURLMap;
char                    cURLManager::errorBuffer[CURL_ERROR_SIZE];

cURLManager::cURLManager()
{
  CURLcode result;

  theData   = NULL;
  theLen    = 0;
  errorCode = CURLE_OK;
  added     = false;

  if (!inited)
    setup();

  easyHandle = curl_easy_init();
  if (!easyHandle) {
    DEBUG1("Something wrong with CURL\n");
    return;
  }

  if (debugLevel >= 2) {
    result = curl_easy_setopt(easyHandle, CURLOPT_VERBOSE, (long)1);
    if (result != CURLE_OK) {
      DEBUG1("CURLOPT_VERBOSE error: %d\n", result);
    }
  }

  result = curl_easy_setopt(easyHandle, CURLOPT_ERRORBUFFER, errorBuffer);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_ERRORBUFFER error: %d\n", result);
  }

  result = curl_easy_setopt(easyHandle, CURLOPT_NOSIGNAL, true);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_NOSIGNAL error %d : %s\n", result, errorBuffer);
  }

  result = curl_easy_setopt(easyHandle, CURLOPT_WRITEFUNCTION,
			    cURLManager::writeFunction);
  if (result != CURLE_OK)
    DEBUG1("CURLOPT_WRITEFUNCTION error %d : %s\n", result, errorBuffer);

  result = curl_easy_setopt(easyHandle, CURLOPT_WRITEDATA, this);
  if (result != CURLE_OK)
    DEBUG1("CURLOPT_WRITEDATA error %d : %s\n", result, errorBuffer);

  cURLMap[easyHandle] = this;
}

cURLManager::~cURLManager()
{
  if (added)
    removeHandle();
  cURLMap.erase(easyHandle);
  curl_easy_cleanup(easyHandle);
  free(theData);
}

void cURLManager::setup()
{
  CURLcode result;

  DEBUG1("LIBCURL: %s\n", curl_version());
  if ((result = curl_global_init(CURL_GLOBAL_NOTHING)))
    DEBUG1("cURL Global init Error: %d\n", result);
  multiHandle = curl_multi_init();
  if (!multiHandle)
    DEBUG1("Unexpected error creating multi handle from libcurl \n");
  inited = true;
}

size_t cURLManager::writeFunction(void *ptr, size_t size, size_t nmemb,
				  void *stream)
{
  int len = size * nmemb;
  ((cURLManager*)stream)->collectData((char*)ptr, len);
  return len;
}

void cURLManager::setTimeout(long timeout)
{
  CURLcode result;

  result = curl_easy_setopt(easyHandle, CURLOPT_TIMEOUT, timeout);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_TIMEOUT error %d : %s\n", result, errorBuffer);
  }
}

void cURLManager::setNoBody()
{
  CURLcode result;
  long     nobody = 1;

  result = curl_easy_setopt(easyHandle, CURLOPT_NOBODY, nobody);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_NOBODY error %d : %s\n", result, errorBuffer);
  }
}

void cURLManager::setGetMode()
{
  CURLcode result;
  long     get = 1;

  result = curl_easy_setopt(easyHandle, CURLOPT_HTTPGET, get);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_GET error %d : %s\n", result, errorBuffer);
  }
}

void cURLManager::setURL(const std::string url)
{
  CURLcode result;

  DEBUG4("Tried to fetch URL: %s\n", url.c_str());

  if (url == "") {
    result = curl_easy_setopt(easyHandle, CURLOPT_URL, NULL);
  } else {
    usedUrl = url;
    result = curl_easy_setopt(easyHandle, CURLOPT_URL, usedUrl.c_str());
    DEBUG2("CURLOPT_URL is : %s\n", usedUrl.c_str());
  }
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_URL error %d : %s\n", result, errorBuffer);
  }
}

void cURLManager::setProgressFunction(curl_progress_callback func, void* data)
{
  CURLcode result;
  if (func != NULL) {
    result = curl_easy_setopt(easyHandle, CURLOPT_PROGRESSFUNCTION, func);
    if (result == CURLE_OK)
      result = curl_easy_setopt(easyHandle, CURLOPT_PROGRESSDATA, data);
    if (result == CURLE_OK)
      result = curl_easy_setopt(easyHandle, CURLOPT_NOPROGRESS, 0);
  } else {
   result = curl_easy_setopt(easyHandle, CURLOPT_NOPROGRESS, 1);
  }
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_SET_PROGRESS error %d : %s\n", result, errorBuffer);
  }
}

void cURLManager::setRequestFileTime(bool request)
{
  CURLcode result;
  long     requestFileTime = request ? 1 : 0;
  result = curl_easy_setopt(easyHandle, CURLOPT_FILETIME, requestFileTime);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_FILETIME error %d : %s\n", result, errorBuffer);
  }
}

void cURLManager::addHandle()
{
  CURLMcode result = curl_multi_add_handle(multiHandle, easyHandle);
  if (result > CURLM_OK)
    DEBUG1("Error while adding easy handle from libcurl %d : %s\n",
	   result, errorBuffer);
  added = true;
}

void cURLManager::removeHandle()
{
  if (!added)
    return;
  CURLMcode result = curl_multi_remove_handle(multiHandle, easyHandle);
  if (result != CURLM_OK)
    DEBUG1("Error while removing easy handle from libcurl %d : %s\n",
	   result, errorBuffer);
  added = false;
}

void cURLManager::finalization(char *, unsigned int, bool)
{
}

void cURLManager::collectData(char* ptr, int len)
{
  unsigned char *newData = (unsigned char *)realloc(theData, theLen + len);
  if (!newData) {
    DEBUG1("memory exhausted\n");
  } else {
    memcpy(newData + theLen, ptr, len);
    theLen += len;
    theData = newData;
  }
}

int cURLManager::perform()
{
  if (!inited)
    setup();

  int activeTransfers = 0;
  CURLMcode result;
  while (true) {
    result = curl_multi_perform(multiHandle, &activeTransfers);
    if (result != CURLM_CALL_MULTI_PERFORM)
      break;
  }
  if (result != CURLM_OK)
    DEBUG1("Error while doing multi_perform from libcurl %d : %s\n",
	   result, errorBuffer);

  int      msgs_in_queue;
  CURLMsg *pendingMsg;
  CURL    *easy;

  while (true) {
    pendingMsg = curl_multi_info_read(multiHandle, &msgs_in_queue);
    if (!pendingMsg)
      break;

    easy        = pendingMsg->easy_handle;

    if (cURLMap.count(easy))
      cURLMap[easy]->infoComplete(pendingMsg->data.result);

    if (msgs_in_queue <= 0)
      break;
  }

  return activeTransfers;
}

void cURLManager::infoComplete(CURLcode result)
{
  if (result != CURLE_OK)
    DEBUG1("File transfer terminated with error from libcurl %d : %s\n",
	   result, errorBuffer);
  finalization((char *)theData, theLen, result == CURLE_OK);
  free(theData);
  removeHandle();
  theData = NULL;
  theLen  = 0;
}

bool cURLManager::getFileTime(time_t &t)
{
  long filetime;
  CURLcode result;
  result = curl_easy_getinfo(easyHandle, CURLINFO_FILETIME, &filetime);
  if (result) {
    DEBUG1("CURLINFO_FILETIME error %d : %s\n", result, errorBuffer);
    return false;
  }
  t = (time_t)filetime;
  return true;
}

void cURLManager::setTimeCondition(timeCondition condition, time_t &t)
{
  CURLcode result;

  switch (condition) {
  case None:
    result = curl_easy_setopt(easyHandle,
			      CURLOPT_TIMECONDITION,
			      CURL_TIMECOND_NONE);
    if (result != CURLE_OK) {
      errorCode = result;
      DEBUG1("CURLOPT_TIMECONDITION error %d : %s\n", result, errorBuffer);
    }
    break;
  case ModifiedSince:
    result = curl_easy_setopt(easyHandle,
			      CURLOPT_TIMECONDITION,
			      CURL_TIMECOND_IFMODSINCE);
    if (result != CURLE_OK) {
      errorCode = result;
      DEBUG1("CURLOPT_TIMECONDITION error %d : %s\n", result, errorBuffer);
    }
    result = curl_easy_setopt(easyHandle,
			      CURLOPT_TIMEVALUE,
			      (long)t);
    if (result != CURLE_OK) {
      errorCode = result;
      DEBUG1("CURLOPT_TIMEVALUE error %d : %s\n", result, errorBuffer);
    }
    break;
  default:
    break;
  }
}

//**************************resourceGeter*************************

resourceGeter::resourceGeter() : cURLManager()
{
	doingStuff = false;
}

resourceGeter::~resourceGeter()
{

}

void resourceGeter::addResource ( trResourceItem &item )
{
	resources.push_back(item);

	if (!doingStuff)
		getResource();
}

void resourceGeter::flush ( void )
{
	resources.clear();
	doingStuff = false;
}

void resourceGeter::finalization(char *data, unsigned int length, bool good)
{
	if (!resources.size() || !doingStuff)
		return;	// we are suposed to be done

	// this is who we are suposed to be geting
	trResourceItem item = resources[0];
	resources.erase(resources.begin());
	if (good)
	{
		// save the thing
		FILE *fp = fopen(item.filePath.c_str(),"wb");
		if (fp)
		{
			fwrite(data,length,1,fp);
			fclose(fp);
		}

		// maybe send a message here saying we did it?
	}

	// do the next one if we must
	getResource();
}

bool resourceGeter::itemExists ( trResourceItem &item )
{
	// save the thing
	FILE *fp = fopen(item.filePath.c_str(),"rb");
	if (fp)
	{
		fclose(fp);
		return true;
	}
	return false;
}

void resourceGeter::getResource ( void )
{
	while ( resources.size() || itemExists(resources[0]) )
		resources.erase(resources.begin());

	if ( !resources.size() )
		doingStuff = false;
	else
	{
		trResourceItem item = resources[0];

		doingStuff = true;
		setURL(item.URL);
		perform();
	}
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>call the method the man says we should call to start a job<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// class interface header
#include "cURLManager.h"

// common implementation headers
#include "bzfio.h"

bool                    cURLManager::inited      = false;
CURLM                  *cURLManager::multiHandle = NULL;
std::map<CURL*,
	 cURLManager*>  cURLManager::cURLMap;
char                    cURLManager::errorBuffer[CURL_ERROR_SIZE];

cURLManager::cURLManager()
{
  CURLcode result;

  theData   = NULL;
  theLen    = 0;
  errorCode = CURLE_OK;
  added     = false;

  if (!inited)
    setup();

  easyHandle = curl_easy_init();
  if (!easyHandle) {
    DEBUG1("Something wrong with CURL\n");
    return;
  }

  if (debugLevel >= 2) {
    result = curl_easy_setopt(easyHandle, CURLOPT_VERBOSE, (long)1);
    if (result != CURLE_OK) {
      DEBUG1("CURLOPT_VERBOSE error: %d\n", result);
    }
  }

  result = curl_easy_setopt(easyHandle, CURLOPT_ERRORBUFFER, errorBuffer);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_ERRORBUFFER error: %d\n", result);
  }

  result = curl_easy_setopt(easyHandle, CURLOPT_NOSIGNAL, true);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_NOSIGNAL error %d : %s\n", result, errorBuffer);
  }

  result = curl_easy_setopt(easyHandle, CURLOPT_WRITEFUNCTION,
			    cURLManager::writeFunction);
  if (result != CURLE_OK)
    DEBUG1("CURLOPT_WRITEFUNCTION error %d : %s\n", result, errorBuffer);

  result = curl_easy_setopt(easyHandle, CURLOPT_WRITEDATA, this);
  if (result != CURLE_OK)
    DEBUG1("CURLOPT_WRITEDATA error %d : %s\n", result, errorBuffer);

  cURLMap[easyHandle] = this;
}

cURLManager::~cURLManager()
{
  if (added)
    removeHandle();
  cURLMap.erase(easyHandle);
  curl_easy_cleanup(easyHandle);
  free(theData);
}

void cURLManager::setup()
{
  CURLcode result;

  DEBUG1("LIBCURL: %s\n", curl_version());
  if ((result = curl_global_init(CURL_GLOBAL_NOTHING)))
    DEBUG1("cURL Global init Error: %d\n", result);
  multiHandle = curl_multi_init();
  if (!multiHandle)
    DEBUG1("Unexpected error creating multi handle from libcurl \n");
  inited = true;
}

size_t cURLManager::writeFunction(void *ptr, size_t size, size_t nmemb,
				  void *stream)
{
  int len = size * nmemb;
  ((cURLManager*)stream)->collectData((char*)ptr, len);
  return len;
}

void cURLManager::setTimeout(long timeout)
{
  CURLcode result;

  result = curl_easy_setopt(easyHandle, CURLOPT_TIMEOUT, timeout);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_TIMEOUT error %d : %s\n", result, errorBuffer);
  }
}

void cURLManager::setNoBody()
{
  CURLcode result;
  long     nobody = 1;

  result = curl_easy_setopt(easyHandle, CURLOPT_NOBODY, nobody);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_NOBODY error %d : %s\n", result, errorBuffer);
  }
}

void cURLManager::setGetMode()
{
  CURLcode result;
  long     get = 1;

  result = curl_easy_setopt(easyHandle, CURLOPT_HTTPGET, get);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_GET error %d : %s\n", result, errorBuffer);
  }
}

void cURLManager::setURL(const std::string url)
{
  CURLcode result;

  DEBUG4("Tried to fetch URL: %s\n", url.c_str());

  if (url == "") {
    result = curl_easy_setopt(easyHandle, CURLOPT_URL, NULL);
  } else {
    usedUrl = url;
    result = curl_easy_setopt(easyHandle, CURLOPT_URL, usedUrl.c_str());
    DEBUG2("CURLOPT_URL is : %s\n", usedUrl.c_str());
  }
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_URL error %d : %s\n", result, errorBuffer);
  }
}

void cURLManager::setProgressFunction(curl_progress_callback func, void* data)
{
  CURLcode result;
  if (func != NULL) {
    result = curl_easy_setopt(easyHandle, CURLOPT_PROGRESSFUNCTION, func);
    if (result == CURLE_OK)
      result = curl_easy_setopt(easyHandle, CURLOPT_PROGRESSDATA, data);
    if (result == CURLE_OK)
      result = curl_easy_setopt(easyHandle, CURLOPT_NOPROGRESS, 0);
  } else {
   result = curl_easy_setopt(easyHandle, CURLOPT_NOPROGRESS, 1);
  }
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_SET_PROGRESS error %d : %s\n", result, errorBuffer);
  }
}

void cURLManager::setRequestFileTime(bool request)
{
  CURLcode result;
  long     requestFileTime = request ? 1 : 0;
  result = curl_easy_setopt(easyHandle, CURLOPT_FILETIME, requestFileTime);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_FILETIME error %d : %s\n", result, errorBuffer);
  }
}

void cURLManager::addHandle()
{
  CURLMcode result = curl_multi_add_handle(multiHandle, easyHandle);
  if (result > CURLM_OK)
    DEBUG1("Error while adding easy handle from libcurl %d : %s\n",
	   result, errorBuffer);
  added = true;
}

void cURLManager::removeHandle()
{
  if (!added)
    return;
  CURLMcode result = curl_multi_remove_handle(multiHandle, easyHandle);
  if (result != CURLM_OK)
    DEBUG1("Error while removing easy handle from libcurl %d : %s\n",
	   result, errorBuffer);
  added = false;
}

void cURLManager::finalization(char *, unsigned int, bool)
{
}

void cURLManager::collectData(char* ptr, int len)
{
  unsigned char *newData = (unsigned char *)realloc(theData, theLen + len);
  if (!newData) {
    DEBUG1("memory exhausted\n");
  } else {
    memcpy(newData + theLen, ptr, len);
    theLen += len;
    theData = newData;
  }
}

int cURLManager::perform()
{
  if (!inited)
    setup();

  int activeTransfers = 0;
  CURLMcode result;
  while (true) {
    result = curl_multi_perform(multiHandle, &activeTransfers);
    if (result != CURLM_CALL_MULTI_PERFORM)
      break;
  }
  if (result != CURLM_OK)
    DEBUG1("Error while doing multi_perform from libcurl %d : %s\n",
	   result, errorBuffer);

  int      msgs_in_queue;
  CURLMsg *pendingMsg;
  CURL    *easy;

  while (true) {
    pendingMsg = curl_multi_info_read(multiHandle, &msgs_in_queue);
    if (!pendingMsg)
      break;

    easy        = pendingMsg->easy_handle;

    if (cURLMap.count(easy))
      cURLMap[easy]->infoComplete(pendingMsg->data.result);

    if (msgs_in_queue <= 0)
      break;
  }

  return activeTransfers;
}

void cURLManager::infoComplete(CURLcode result)
{
  if (result != CURLE_OK)
    DEBUG1("File transfer terminated with error from libcurl %d : %s\n",
	   result, errorBuffer);
  finalization((char *)theData, theLen, result == CURLE_OK);
  free(theData);
  removeHandle();
  theData = NULL;
  theLen  = 0;
}

bool cURLManager::getFileTime(time_t &t)
{
  long filetime;
  CURLcode result;
  result = curl_easy_getinfo(easyHandle, CURLINFO_FILETIME, &filetime);
  if (result) {
    DEBUG1("CURLINFO_FILETIME error %d : %s\n", result, errorBuffer);
    return false;
  }
  t = (time_t)filetime;
  return true;
}

void cURLManager::setTimeCondition(timeCondition condition, time_t &t)
{
  CURLcode result;

  switch (condition) {
  case None:
    result = curl_easy_setopt(easyHandle,
			      CURLOPT_TIMECONDITION,
			      CURL_TIMECOND_NONE);
    if (result != CURLE_OK) {
      errorCode = result;
      DEBUG1("CURLOPT_TIMECONDITION error %d : %s\n", result, errorBuffer);
    }
    break;
  case ModifiedSince:
    result = curl_easy_setopt(easyHandle,
			      CURLOPT_TIMECONDITION,
			      CURL_TIMECOND_IFMODSINCE);
    if (result != CURLE_OK) {
      errorCode = result;
      DEBUG1("CURLOPT_TIMECONDITION error %d : %s\n", result, errorBuffer);
    }
    result = curl_easy_setopt(easyHandle,
			      CURLOPT_TIMEVALUE,
			      (long)t);
    if (result != CURLE_OK) {
      errorCode = result;
      DEBUG1("CURLOPT_TIMEVALUE error %d : %s\n", result, errorBuffer);
    }
    break;
  default:
    break;
  }
}

//**************************resourceGeter*************************

resourceGeter::resourceGeter() : cURLManager()
{
	doingStuff = false;
}

resourceGeter::~resourceGeter()
{

}

void resourceGeter::addResource ( trResourceItem &item )
{
	resources.push_back(item);

	if (!doingStuff)
		getResource();
}

void resourceGeter::flush ( void )
{
	resources.clear();
	doingStuff = false;
}

void resourceGeter::finalization(char *data, unsigned int length, bool good)
{
	if (!resources.size() || !doingStuff)
		return;	// we are suposed to be done

	// this is who we are suposed to be geting
	trResourceItem item = resources[0];
	resources.erase(resources.begin());
	if (good)
	{
		// save the thing
		FILE *fp = fopen(item.filePath.c_str(),"wb");
		if (fp)
		{
			fwrite(data,length,1,fp);
			fclose(fp);
		}

		// maybe send a message here saying we did it?
	}

	// do the next one if we must
	getResource();
}

bool resourceGeter::itemExists ( trResourceItem &item )
{
	// save the thing
	FILE *fp = fopen(item.filePath.c_str(),"rb");
	if (fp)
	{
		fclose(fp);
		return true;
	}
	return false;
}

void resourceGeter::getResource ( void )
{
	while ( resources.size() || itemExists(resources[0]) )
		resources.erase(resources.begin());

	if ( !resources.size() )
		doingStuff = false;
	else
	{
		trResourceItem item = resources[0];

		doingStuff = true;
		setURL(item.URL);
		addHandle();
	}
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/*
 * opencog/persist/sql/PersistModule.cc
 *
 * Copyright (c) 2008 by OpenCog Foundation
 * Copyright (c) 2008, 2009, 2013 Linas Vepstas <linasvepstas@gmail.com>
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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 Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atomspace/BackingStore.h>
#include <opencog/guile/SchemePrimitive.h>
#include <opencog/nlp/types/atom_types.h>

#include "PersistModule.h"
#include "AtomStorage.h"

using namespace opencog;

namespace opencog {
class SQLBackingStore : public BackingStore
{
	private:
		AtomStorage *_store;
	public:
		SQLBackingStore();
		void set_store(AtomStorage *);

		virtual NodePtr getNode(Type, const char *) const;
		virtual LinkPtr getLink(Type, const HandleSeq&) const;
		virtual AtomPtr getAtom(Handle) const;
		virtual HandleSeq getIncomingSet(Handle) const;
		virtual void storeAtom(Handle);
		virtual void loadType(AtomTable&, Type);
		virtual void barrier();
};
};

SQLBackingStore::SQLBackingStore()
{
	_store = NULL;
}

void SQLBackingStore::set_store(AtomStorage *as)
{
	_store = as;
}

NodePtr SQLBackingStore::getNode(Type t, const char *name) const
{
	return _store->getNode(t, name);
}

LinkPtr SQLBackingStore::getLink(Type t, const std::vector<Handle>& oset) const
{
	return _store->getLink(t, oset);
}

AtomPtr SQLBackingStore::getAtom(Handle h) const
{
	return _store->getAtom(h);
}

HandleSeq SQLBackingStore::getIncomingSet(Handle h) const
{
	return _store->getIncomingSet(h);
}

void SQLBackingStore::storeAtom(Handle h)
{
	_store->storeAtom(h);
}

void SQLBackingStore::loadType(AtomTable& at, Type t)
{
	_store->loadType(at, t);
}

void SQLBackingStore::barrier()
{
	_store->flushStoreQueue();
}

DECLARE_MODULE(PersistModule);

PersistModule::PersistModule(CogServer& cs) : Module(cs), _store(NULL)
{
	_backing = new SQLBackingStore();

	// XXX FIXME Huge hack alert.
	// As of 2013, no one uses this thing, except for NLP processing.
	// Since I'm too lazy to find an elegant solution right now, I'm
	// just going to hack this in.  Fix this someday.
	//
	// Anyway, what the below does is to ignore these certain types,
	// when they are to be fetched from the backing store.  This can
	// speed up document processing, since we know that word instances
	// and documents and sentences will not be stored in the database.
	// Thus, we don't even try to fetch these.

#define NLP_HACK 1
#ifdef NLP_HACK
	_backing->_ignored_types.insert(DOCUMENT_NODE);
	_backing->_ignored_types.insert(SENTENCE_NODE);
	_backing->_ignored_types.insert(PARSE_NODE);
	_backing->_ignored_types.insert(PARSE_LINK);
	_backing->_ignored_types.insert(WORD_INSTANCE_NODE);
	_backing->_ignored_types.insert(WORD_INSTANCE_LINK);
#endif // NLP_HACK

	do_close_register();
	do_load_register();
	do_open_register();
	do_store_register();

#ifdef HAVE_GUILE
	// XXX These should be declared in some generic persistance module,
	// as they are not specific to the SQL backend only.
	// But I guess this is an OK home for now.
	define_scheme_primitive("fetch-atom", &PersistModule::fetch_atom, this);
	define_scheme_primitive("fetch-incoming-set", &PersistModule::fetch_incoming_set, this);
	define_scheme_primitive("store-atom", &PersistModule::store_atom, this);
	define_scheme_primitive("load-atoms-of-type", &PersistModule::load_type, this);
	define_scheme_primitive("barrier", &PersistModule::barrier, this);
#endif
}

PersistModule::~PersistModule()
{
	do_close_unregister();
	do_load_unregister();
	do_open_unregister();
	do_store_unregister();
	delete _backing;
}

void PersistModule::init(void)
{
}

std::string PersistModule::do_close(Request *dummy, std::list<std::string> args)
{
	if (!args.empty())
		return "sql-close: Error: Unexpected argument\n";

	if (_store == NULL)
		return "sql-close: Error: Database not open\n";

	_cogserver.getAtomSpace().getImpl().unregisterBackingStore(_backing);

	_backing->set_store(NULL);
	delete _store;
	_store = NULL;
	return "Database closed\n";
}

std::string PersistModule::do_load(Request *dummy, std::list<std::string> args)
{
	if (!args.empty())
		return "sql-load: Error: Unexpected argument\n";

	if (_store == NULL)
		return "sql-load: Error: Database not open\n";

	// XXX TODO: this should probably be done in a separate thread.
	_store->load(const_cast<AtomTable&>(_cogserver.getAtomSpace().getAtomTable()));

	return "Database load completed\n";
}

std::string PersistModule::do_open(Request *dummy, std::list<std::string> args)
{
	if (args.size() != 3)
		return "sql-open: Error: invalid command syntax\n"
		       "Usage: sql-open <dbname> <username> <auth>\n";

	std::string dbname   = args.front(); args.pop_front();
	std::string username = args.front(); args.pop_front();
	std::string auth	   = args.front(); args.pop_front();

	_store = new AtomStorage(dbname, username, auth);
	if (!_store)
		return "sql-open: Error: Unable to open the database\n";

	if (!_store->connected())
	{
		delete _store;
		_store = NULL;
		return "sql-open: Error: Unable to connect to the database\n";
	}

	// reserve() is critical here, to reserve UUID range.
	_store->reserve();
	_backing->set_store(_store);
	_cogserver.getAtomSpace().getImpl().registerBackingStore(_backing);

	std::string rc = "Opened \"" + dbname + "\" as user \"" + username + "\"\n";
	return rc;
}

std::string PersistModule::do_store(Request *dummy, std::list<std::string> args)
{
	if (!args.empty())
		return "sql-store: Error: Unexpected argument\n";

	if (_store == NULL)
		return "sql-store: Error: Database not open\n";

	// XXX TODO This should really be started in a new thread ...
	_store->store(const_cast<AtomTable&>(_cogserver.getAtomSpace().getAtomTable()));

	return "Database store completed\n";
}

// =====================================================================
// XXX TODO: the methods  below really belong in their own module,
// independent of this SQL module; they would be applicable for
// any backend, not just the SQL backend.
Handle PersistModule::fetch_atom(Handle h)
{
	AtomSpace *as = &_cogserver.getAtomSpace();
	h = as->getImpl().fetchAtom(h);
	return h;
}

Handle PersistModule::fetch_incoming_set(Handle h)
{
	AtomSpace *as = &_cogserver.getAtomSpace();
	// The "false" flag here means that the fetch is NOT recursive.
	h = as->getImpl().fetchIncomingSet(h, false);
	return h;
}

/**
 * Store the single atom to the backing store hanging off the atom-space
 */
Handle PersistModule::store_atom(Handle h)
{
	AtomSpace *as = &_cogserver.getAtomSpace();
	as->getImpl().storeAtom(h);
	return h;
}

void PersistModule::load_type(Type t)
{
	AtomSpace *as = &_cogserver.getAtomSpace();
	as->getImpl().loadType(t);
}

void PersistModule::barrier(void)
{
	AtomSpace *as = &_cogserver.getAtomSpace();
	as->getImpl().barrier();
}

<commit_msg>Ignore more link types<commit_after>/*
 * opencog/persist/sql/PersistModule.cc
 *
 * Copyright (c) 2008 by OpenCog Foundation
 * Copyright (c) 2008, 2009, 2013 Linas Vepstas <linasvepstas@gmail.com>
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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 Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atomspace/BackingStore.h>
#include <opencog/guile/SchemePrimitive.h>
#include <opencog/nlp/types/atom_types.h>

#include "PersistModule.h"
#include "AtomStorage.h"

using namespace opencog;

namespace opencog {
class SQLBackingStore : public BackingStore
{
	private:
		AtomStorage *_store;
	public:
		SQLBackingStore();
		void set_store(AtomStorage *);

		virtual NodePtr getNode(Type, const char *) const;
		virtual LinkPtr getLink(Type, const HandleSeq&) const;
		virtual AtomPtr getAtom(Handle) const;
		virtual HandleSeq getIncomingSet(Handle) const;
		virtual void storeAtom(Handle);
		virtual void loadType(AtomTable&, Type);
		virtual void barrier();
};
};

SQLBackingStore::SQLBackingStore()
{
	_store = NULL;
}

void SQLBackingStore::set_store(AtomStorage *as)
{
	_store = as;
}

NodePtr SQLBackingStore::getNode(Type t, const char *name) const
{
	return _store->getNode(t, name);
}

LinkPtr SQLBackingStore::getLink(Type t, const std::vector<Handle>& oset) const
{
	return _store->getLink(t, oset);
}

AtomPtr SQLBackingStore::getAtom(Handle h) const
{
	return _store->getAtom(h);
}

HandleSeq SQLBackingStore::getIncomingSet(Handle h) const
{
	return _store->getIncomingSet(h);
}

void SQLBackingStore::storeAtom(Handle h)
{
	_store->storeAtom(h);
}

void SQLBackingStore::loadType(AtomTable& at, Type t)
{
	_store->loadType(at, t);
}

void SQLBackingStore::barrier()
{
	_store->flushStoreQueue();
}

DECLARE_MODULE(PersistModule);

PersistModule::PersistModule(CogServer& cs) : Module(cs), _store(NULL)
{
	_backing = new SQLBackingStore();

	// XXX FIXME Huge hack alert.
	// As of 2013, no one uses this thing, except for NLP processing.
	// Since I'm too lazy to find an elegant solution right now, I'm
	// just going to hack this in.  Fix this someday.
	//
	// Anyway, what the below does is to ignore these certain types,
	// when they are to be fetched from the backing store.  This can
	// speed up document processing, since we know that word instances
	// and documents and sentences will not be stored in the database.
	// Thus, we don't even try to fetch these.

#define NLP_HACK 1
#ifdef NLP_HACK
	_backing->_ignored_types.insert(VARIABLE_NODE);
	_backing->_ignored_types.insert(VARIABLE_TYPE_NODE);
	_backing->_ignored_types.insert(TYPED_VARIABLE_LINK);
	_backing->_ignored_types.insert(BIND_LINK);

	_backing->_ignored_types.insert(DOCUMENT_NODE);
	_backing->_ignored_types.insert(SENTENCE_NODE);
	_backing->_ignored_types.insert(PARSE_NODE);
	_backing->_ignored_types.insert(PARSE_LINK);
	_backing->_ignored_types.insert(WORD_INSTANCE_NODE);
	_backing->_ignored_types.insert(WORD_INSTANCE_LINK);
#endif // NLP_HACK

	do_close_register();
	do_load_register();
	do_open_register();
	do_store_register();

#ifdef HAVE_GUILE
	// XXX These should be declared in some generic persistance module,
	// as they are not specific to the SQL backend only.
	// But I guess this is an OK home for now.
	define_scheme_primitive("fetch-atom", &PersistModule::fetch_atom, this);
	define_scheme_primitive("fetch-incoming-set", &PersistModule::fetch_incoming_set, this);
	define_scheme_primitive("store-atom", &PersistModule::store_atom, this);
	define_scheme_primitive("load-atoms-of-type", &PersistModule::load_type, this);
	define_scheme_primitive("barrier", &PersistModule::barrier, this);
#endif
}

PersistModule::~PersistModule()
{
	do_close_unregister();
	do_load_unregister();
	do_open_unregister();
	do_store_unregister();
	delete _backing;
}

void PersistModule::init(void)
{
}

std::string PersistModule::do_close(Request *dummy, std::list<std::string> args)
{
	if (!args.empty())
		return "sql-close: Error: Unexpected argument\n";

	if (_store == NULL)
		return "sql-close: Error: Database not open\n";

	_cogserver.getAtomSpace().getImpl().unregisterBackingStore(_backing);

	_backing->set_store(NULL);
	delete _store;
	_store = NULL;
	return "Database closed\n";
}

std::string PersistModule::do_load(Request *dummy, std::list<std::string> args)
{
	if (!args.empty())
		return "sql-load: Error: Unexpected argument\n";

	if (_store == NULL)
		return "sql-load: Error: Database not open\n";

	// XXX TODO: this should probably be done in a separate thread.
	_store->load(const_cast<AtomTable&>(_cogserver.getAtomSpace().getAtomTable()));

	return "Database load completed\n";
}

std::string PersistModule::do_open(Request *dummy, std::list<std::string> args)
{
	if (args.size() != 3)
		return "sql-open: Error: invalid command syntax\n"
		       "Usage: sql-open <dbname> <username> <auth>\n";

	std::string dbname   = args.front(); args.pop_front();
	std::string username = args.front(); args.pop_front();
	std::string auth	   = args.front(); args.pop_front();

	_store = new AtomStorage(dbname, username, auth);
	if (!_store)
		return "sql-open: Error: Unable to open the database\n";

	if (!_store->connected())
	{
		delete _store;
		_store = NULL;
		return "sql-open: Error: Unable to connect to the database\n";
	}

	// reserve() is critical here, to reserve UUID range.
	_store->reserve();
	_backing->set_store(_store);
	_cogserver.getAtomSpace().getImpl().registerBackingStore(_backing);

	std::string rc = "Opened \"" + dbname + "\" as user \"" + username + "\"\n";
	return rc;
}

std::string PersistModule::do_store(Request *dummy, std::list<std::string> args)
{
	if (!args.empty())
		return "sql-store: Error: Unexpected argument\n";

	if (_store == NULL)
		return "sql-store: Error: Database not open\n";

	// XXX TODO This should really be started in a new thread ...
	_store->store(const_cast<AtomTable&>(_cogserver.getAtomSpace().getAtomTable()));

	return "Database store completed\n";
}

// =====================================================================
// XXX TODO: the methods  below really belong in their own module,
// independent of this SQL module; they would be applicable for
// any backend, not just the SQL backend.
Handle PersistModule::fetch_atom(Handle h)
{
	AtomSpace *as = &_cogserver.getAtomSpace();
	h = as->getImpl().fetchAtom(h);
	return h;
}

Handle PersistModule::fetch_incoming_set(Handle h)
{
	AtomSpace *as = &_cogserver.getAtomSpace();
	// The "false" flag here means that the fetch is NOT recursive.
	h = as->getImpl().fetchIncomingSet(h, false);
	return h;
}

/**
 * Store the single atom to the backing store hanging off the atom-space
 */
Handle PersistModule::store_atom(Handle h)
{
	AtomSpace *as = &_cogserver.getAtomSpace();
	as->getImpl().storeAtom(h);
	return h;
}

void PersistModule::load_type(Type t)
{
	AtomSpace *as = &_cogserver.getAtomSpace();
	as->getImpl().loadType(t);
}

void PersistModule::barrier(void)
{
	AtomSpace *as = &_cogserver.getAtomSpace();
	as->getImpl().barrier();
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DAVRequestEnvironment.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 05:33:41 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _DAVREQUESTENVIRONMENT_HXX_
#define _DAVREQUESTENVIRONMENT_HXX_

#ifndef _RTL_REF_HXX_
#include <rtl/ref.hxx>
#endif

#ifndef _DAVAUTHLISTENER_HXX_
#include "DAVAuthListener.hxx"
#endif

namespace webdav_ucp
{

struct DAVRequestEnvironment
{
    rtl::OUString m_aRequestURI;
    rtl::Reference< DAVAuthListener >     m_xAuthListener;
//    rtl::Reference< DAVStatusListener >   m_xStatusListener;
//    rtl::Reference< DAVProgressListener > m_xStatusListener;

    DAVRequestEnvironment( const rtl::OUString & rRequestURI,
                           const rtl::Reference< DAVAuthListener > & xListener )
    : m_aRequestURI( rRequestURI ), m_xAuthListener( xListener ) {}

    DAVRequestEnvironment() {}
};

} // namespace webdav_ucp

#endif // _DAVREQUESTENVIRONMENT_HXX_
<commit_msg>INTEGRATION: CWS updatefeed (1.6.42); FILE MERGED 2006/12/04 16:54:47 kso 1.6.42.1: #i72055# - Added support for XWebDAVCommandEnvironment.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DAVRequestEnvironment.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-13 15:03:47 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _DAVREQUESTENVIRONMENT_HXX_
#define _DAVREQUESTENVIRONMENT_HXX_

#include <vector>

#ifndef _RTL_REF_HXX_
#include <rtl/ref.hxx>
#endif

#ifndef _DAVAUTHLISTENER_HXX_
#include "DAVAuthListener.hxx"
#endif

namespace webdav_ucp
{
    typedef std::pair< rtl::OUString, rtl::OUString > DAVRequestHeader;
    typedef std::vector< DAVRequestHeader > DAVRequestHeaders;

struct DAVRequestEnvironment
{
    rtl::OUString m_aRequestURI;
    rtl::Reference< DAVAuthListener >     m_xAuthListener;
//    rtl::Reference< DAVStatusListener >   m_xStatusListener;
//    rtl::Reference< DAVProgressListener > m_xStatusListener;
    DAVRequestHeaders                     m_aRequestHeaders;

    DAVRequestEnvironment( const rtl::OUString & rRequestURI,
                           const rtl::Reference< DAVAuthListener > & xListener,
                           const DAVRequestHeaders & rRequestHeaders )
    : m_aRequestURI( rRequestURI ),
      m_xAuthListener( xListener ),
      m_aRequestHeaders( rRequestHeaders ) {}

    DAVRequestEnvironment() {}
};

} // namespace webdav_ucp

#endif // _DAVREQUESTENVIRONMENT_HXX_
<|endoftext|>


<commit_before>/*!
 * \file painter_stroke_params.hpp
 * \brief file painter_stroke_params.hpp
 *
 * Copyright 2016 by Intel.
 *
 * Contact: kevin.rogovin@intel.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@intel.com>
 *
 */

#pragma once

#include <fastuidraw/painter/painter_shader_data.hpp>
#include <fastuidraw/painter/painter_stroke_shader.hpp>

namespace fastuidraw
{
/*!\addtogroup Painter
 * @{
 */

  /*!
   * \brief
   * Class to specify stroking parameters, data is packed
   * as according to PainterStrokeParams::stroke_data_offset_t.
   */
  class PainterStrokeParams:public PainterItemShaderData
  {
  public:
    /*!
     * \brief
     * Enumeration to specify the units of the stroking radius
     */
    enum stroking_units_t
      {
        /*!
         * Indicates that the stroking units is in local
         * coordinates of the Path being stroking
         */
        path_stroking_units,

        /*!
         * Indicates that the stroking units are in pixels
         */
        pixel_stroking_units,
      };

    /*!
     * \brief
     * Enumeration that provides offsets for the stroking
     * parameters.
     */
    enum stroke_data_offset_t
      {
        /*!
         * Offset to stroke radius (packed as float).
         * The absolute value gives the stroking radius,
         * if teh value is negative then the stroking radius
         * is in units of pixels, if positive it is in local
         * path coordinates.
         */
        stroke_radius_offset,
        stroke_miter_limit_offset, /*!< offset to stroke miter limit (packed as float) */

        stroke_data_size /*!< size of data for stroking*/
      };

    /*!
     * Ctor.
     */
    PainterStrokeParams(void);

    /*!
     * The miter limit for miter joins
     */
    float
    miter_limit(void) const;

    /*!
     * Set the value of miter_limit(void) const
     */
    PainterStrokeParams&
    miter_limit(float f);

    /*!
     * The stroking width, always non-negative
     */
    float
    width(void) const;

    /*!
     * Set the value of width(void) const,
     * values are clamped to be non-negative.
     */
    PainterStrokeParams&
    width(float f);

    /*!
     * The stroking radius, equivalent to
     * \code
     * width() * 0.5
     * \endcode
     */
    float
    radius(void) const;

    /*!
     * Set the value of radius(void) const,
     * equivalent to
     * \code
     * width(2.0 * f)
     * \endcode
     */
    PainterStrokeParams&
    radius(float f);

    /*!
     * Returns the units of the stroking, default value is
     * \ref path_stroking_units
     */
    enum stroking_units_t
    stroking_units(void) const;

    /*!
     * Set the value of stroking_units(void) const,
     * values are clamped to be non-negative.
     */
    PainterStrokeParams&
    stroking_units(enum stroking_units_t);

    /*!
     * Returns a StrokingDataSelectorBase suitable for PainterStrokeParams.
     * \param pixel_arc_stroking_possible if true, will inform that arc-stroking
     *                                    width in \ref pixel_stroking_units is
     *                                    possible.
     */
    static
    reference_counted_ptr<const StrokingDataSelectorBase>
    stroking_data_selector(bool pixel_arc_stroking_possible);
  };

/*! @} */

} //namespace fastuidraw
<commit_msg>fastuidraw/painter/painter_stroke_params: better doxy tags<commit_after>/*!
 * \file painter_stroke_params.hpp
 * \brief file painter_stroke_params.hpp
 *
 * Copyright 2016 by Intel.
 *
 * Contact: kevin.rogovin@intel.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@intel.com>
 *
 */

#pragma once

#include <fastuidraw/painter/painter_shader_data.hpp>
#include <fastuidraw/painter/painter_stroke_shader.hpp>

namespace fastuidraw
{
/*!\addtogroup Painter
 * @{
 */

  /*!
   * \brief
   * Class to specify stroking parameters, data is packed
   * as according to PainterStrokeParams::stroke_data_offset_t.
   */
  class PainterStrokeParams:public PainterItemShaderData
  {
  public:
    /*!
     * \brief
     * Enumeration to specify the units of the stroking radius
     */
    enum stroking_units_t
      {
        /*!
         * Indicates that the stroking units is in local
         * coordinates of the Path being stroking
         */
        path_stroking_units,

        /*!
         * Indicates that the stroking units are in pixels
         */
        pixel_stroking_units,
      };

    /*!
     * \brief
     * Enumeration that provides offsets for the stroking
     * parameters.
     */
    enum stroke_data_offset_t
      {
        /*!
         * Offset to stroke radius (packed as float).
         * The absolute value gives the stroking radius,
         * if teh value is negative then the stroking radius
         * is in units of pixels, if positive it is in local
         * path coordinates.
         */
        stroke_radius_offset,
        stroke_miter_limit_offset, /*!< offset to stroke miter limit (packed as float) */

        stroke_data_size /*!< size of data for stroking*/
      };

    /*!
     * Ctor.
     */
    PainterStrokeParams(void);

    /*!
     * The miter limit for miter joins.
     * Default value is 15.0.
     */
    float
    miter_limit(void) const;

    /*!
     * Set the value of miter_limit(void) const
     */
    PainterStrokeParams&
    miter_limit(float f);

    /*!
     * The stroking width, always non-negative.
     * Default value is 2.0.
     */
    float
    width(void) const;

    /*!
     * Set the value of width(void) const,
     * values are clamped to be non-negative.
     */
    PainterStrokeParams&
    width(float f);

    /*!
     * The stroking radius, equivalent to
     * \code
     * width() * 0.5
     * \endcode
     * Default value is 1.0.
     */
    float
    radius(void) const;

    /*!
     * Set the value of radius(void) const,
     * equivalent to
     * \code
     * width(2.0 * f)
     * \endcode
     */
    PainterStrokeParams&
    radius(float f);

    /*!
     * Returns the units of the stroking, default value is
     * \ref path_stroking_units
     */
    enum stroking_units_t
    stroking_units(void) const;

    /*!
     * Set the value of stroking_units(void) const
     */
    PainterStrokeParams&
    stroking_units(enum stroking_units_t);

    /*!
     * Returns a StrokingDataSelectorBase suitable for PainterStrokeParams.
     * \param pixel_arc_stroking_possible if true, will inform that arc-stroking
     *                                    width in \ref pixel_stroking_units is
     *                                    possible.
     */
    static
    reference_counted_ptr<const StrokingDataSelectorBase>
    stroking_data_selector(bool pixel_arc_stroking_possible);
  };

/*! @} */

} //namespace fastuidraw
<|endoftext|>


<commit_before>// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// +build

#define SYZ_EXECUTOR
#include "common_bsd.h"

#include "executor_posix.h"

#include "executor.h"

// This file is used by both freebsd and netbsd (as a link to executor_bsd.cc).
#if defined(__FreeBSD__)
#include "syscalls_freebsd.h"
#elif defined(__NetBSD__)
#include "syscalls_netbsd.h"
#else
// This is just so that "make executor TARGETOS=freebsd" works on linux.
#include "syscalls_freebsd.h"
#define __syscall syscall
#endif

#include <signal.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>

const int kInFd = 3;
const int kOutFd = 4;

uint32* output_data;
uint32* output_pos;

int main(int argc, char** argv)
{
	if (argc == 2 && strcmp(argv[1], "version") == 0) {
		puts(GOOS " " GOARCH " " SYZ_REVISION " " GIT_REVISION);
		return 0;
	}

	if (mmap(&input_data[0], kMaxInput, PROT_READ, MAP_PRIVATE | MAP_FIXED, kInFd, 0) != &input_data[0])
		fail("mmap of input file failed");
	// The output region is the only thing in executor process for which consistency matters.
	// If it is corrupted ipc package will fail to parse its contents and panic.
	// But fuzzer constantly invents new ways of how to currupt the region,
	// so we map the region at a (hopefully) hard to guess address surrounded by unmapped pages.
	void* const kOutputDataAddr = (void*)0x1ddbc20000;
	output_data = (uint32*)mmap(kOutputDataAddr, kMaxOutput, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, kOutFd, 0);
	if (output_data != kOutputDataAddr)
		fail("mmap of output file failed");
	if (mmap((void*)SYZ_DATA_OFFSET, SYZ_NUM_PAGES * SYZ_PAGE_SIZE, PROT_READ | PROT_WRITE,
		 MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) != (void*)SYZ_DATA_OFFSET)
		fail("mmap of data segment failed");
	// Prevent random programs to mess with these fds.
	// Due to races in collider mode, a program can e.g. ftruncate one of these fds,
	// which will cause fuzzer to crash.
	// That's also the reason why we close kInPipeFd/kOutPipeFd below.
	close(kInFd);
	close(kOutFd);

	// Some minimal sandboxing.
	struct rlimit rlim;
#ifndef __NetBSD__
	// This causes frequent random aborts on netbsd. Reason unknown.
	rlim.rlim_cur = rlim.rlim_max = 128 << 20;
	setrlimit(RLIMIT_AS, &rlim);
#endif
	rlim.rlim_cur = rlim.rlim_max = 8 << 20;
	setrlimit(RLIMIT_MEMLOCK, &rlim);
	rlim.rlim_cur = rlim.rlim_max = 1 << 20;
	setrlimit(RLIMIT_FSIZE, &rlim);
	rlim.rlim_cur = rlim.rlim_max = 1 << 20;
	setrlimit(RLIMIT_STACK, &rlim);
	rlim.rlim_cur = rlim.rlim_max = 0;
	setrlimit(RLIMIT_CORE, &rlim);

	install_segv_handler();
	setup_control_pipes();
	receive_handshake();
	reply_handshake();
	cover_open();

	for (;;) {
		receive_execute(false);
		char cwdbuf[128] = "/syz-tmpXXXXXX";
		if (!mkdtemp(cwdbuf))
			fail("mkdtemp failed");
		int pid = fork();
		if (pid < 0)
			fail("fork failed");
		if (pid == 0) {
			close(kInPipeFd);
			close(kOutPipeFd);
			if (chdir(cwdbuf))
				fail("chdir failed");
			output_pos = output_data;
			execute_one();
			doexit(0);
		}
		int status = 0;
		uint64 start = current_time_ms();
		uint64 last_executed = start;
		uint32 executed_calls = __atomic_load_n(output_data, __ATOMIC_RELAXED);
		for (;;) {
			int res = waitpid(pid, &status, WNOHANG);
			if (res == pid)
				break;
			sleep_ms(1);
			uint64 now = current_time_ms();
			uint32 now_executed = __atomic_load_n(output_data, __ATOMIC_RELAXED);
			if (executed_calls != now_executed) {
				executed_calls = now_executed;
				last_executed = now;
			}
			if ((now - start < 3 * 1000) && (now - last_executed < 500))
				continue;
			kill(pid, SIGKILL);
			while (waitpid(pid, &status, 0) != pid) {
			}
			break;
		}
		status = WEXITSTATUS(status);
		if (status == kFailStatus)
			fail("child failed");
		if (status == kErrorStatus)
			error("child errored");
		remove_dir(cwdbuf);
		reply_execute(0);
	}
	return 0;
}

long execute_syscall(call_t* c, long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8)
{
	if (c->call)
		return c->call(a0, a1, a2, a3, a4, a5, a6, a7, a8);
	return __syscall(c->sys_nr, a0, a1, a2, a3, a4, a5, a6, a7, a8);
}

void cover_open()
{
	if (!flag_cover)
		return;
	for (int i = 0; i < kMaxThreads; i++) {
		thread_t* th = &threads[i];
		th->cover_data = &th->cover_buffer[0];
	}
}

void cover_enable(thread_t* th)
{
}

void cover_reset(thread_t* th)
{
}

uint64 read_cover_size(thread_t* th)
{
	if (!flag_cover)
		return 0;
	// Fallback coverage since we have no real coverage available.
	// We use syscall number or-ed with returned errno value as signal.
	// At least this gives us all combinations of syscall+errno.
	th->cover_data[0] = (th->call_num << 16) | ((th->res == -1 ? th->reserrno : 0) & 0x3ff);
	return 1;
}

uint32* write_output(uint32 v)
{
	if (collide)
		return 0;
	if (output_pos < output_data || (char*)output_pos >= (char*)output_data + kMaxOutput)
		fail("output overflow");
	*output_pos = v;
	return output_pos++;
}

void write_completed(uint32 completed)
{
	__atomic_store_n(output_data, completed, __ATOMIC_RELEASE);
}

bool kcov_comparison_t::ignore() const
{
	return false;
}
<commit_msg>executor: update to support FreeBSD kcov<commit_after>// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// +build

#define SYZ_EXECUTOR
#include "common_bsd.h"

#include "executor_posix.h"

#include "executor.h"

// This file is used by both freebsd and netbsd (as a link to executor_bsd.cc).
#if defined(__FreeBSD__)
#include "syscalls_freebsd.h"
#elif defined(__NetBSD__)
#include "syscalls_netbsd.h"
#else
// This is just so that "make executor TARGETOS=freebsd" works on linux.
#include "syscalls_freebsd.h"
#define __syscall syscall
#endif

#include <fcntl.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>

#if defined(__FreeBSD__)
#define KIOENABLE _IOW('c', 2, int) // Enable coverage recording
#define KIODISABLE _IO('c', 3) // Disable coverage recording
#define KIOSETBUFSIZE _IOW('c', 4, unsigned int) // Set the buffer size

#define KCOV_MODE_NONE -1
#define KCOV_MODE_TRACE_PC 0
#define KCOV_MODE_TRACE_CMP 1
#endif

const int kInFd = 3;
const int kOutFd = 4;

uint32* output_data;
uint32* output_pos;

int main(int argc, char** argv)
{
	if (argc == 2 && strcmp(argv[1], "version") == 0) {
		puts(GOOS " " GOARCH " " SYZ_REVISION " " GIT_REVISION);
		return 0;
	}

	if (mmap(&input_data[0], kMaxInput, PROT_READ, MAP_PRIVATE | MAP_FIXED, kInFd, 0) != &input_data[0])
		fail("mmap of input file failed");
	// The output region is the only thing in executor process for which consistency matters.
	// If it is corrupted ipc package will fail to parse its contents and panic.
	// But fuzzer constantly invents new ways of how to currupt the region,
	// so we map the region at a (hopefully) hard to guess address surrounded by unmapped pages.
	void* const kOutputDataAddr = (void*)0x1ddbc20000;
	output_data = (uint32*)mmap(kOutputDataAddr, kMaxOutput, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, kOutFd, 0);
	if (output_data != kOutputDataAddr)
		fail("mmap of output file failed");
	if (mmap((void*)SYZ_DATA_OFFSET, SYZ_NUM_PAGES * SYZ_PAGE_SIZE, PROT_READ | PROT_WRITE,
		 MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) != (void*)SYZ_DATA_OFFSET)
		fail("mmap of data segment failed");
	// Prevent random programs to mess with these fds.
	// Due to races in collider mode, a program can e.g. ftruncate one of these fds,
	// which will cause fuzzer to crash.
	// That's also the reason why we close kInPipeFd/kOutPipeFd below.
	close(kInFd);
	close(kOutFd);

	// Some minimal sandboxing.
	struct rlimit rlim;
#ifndef __NetBSD__
	// This causes frequent random aborts on netbsd. Reason unknown.
	rlim.rlim_cur = rlim.rlim_max = 128 << 20;
	setrlimit(RLIMIT_AS, &rlim);
#endif
	rlim.rlim_cur = rlim.rlim_max = 8 << 20;
	setrlimit(RLIMIT_MEMLOCK, &rlim);
	rlim.rlim_cur = rlim.rlim_max = 1 << 20;
	setrlimit(RLIMIT_FSIZE, &rlim);
	rlim.rlim_cur = rlim.rlim_max = 1 << 20;
	setrlimit(RLIMIT_STACK, &rlim);
	rlim.rlim_cur = rlim.rlim_max = 0;
	setrlimit(RLIMIT_CORE, &rlim);

	install_segv_handler();
	setup_control_pipes();
	receive_handshake();
	reply_handshake();
	cover_open();

	for (;;) {
		receive_execute(false);
		char cwdbuf[128] = "/syz-tmpXXXXXX";
		if (!mkdtemp(cwdbuf))
			fail("mkdtemp failed");
		int pid = fork();
		if (pid < 0)
			fail("fork failed");
		if (pid == 0) {
			close(kInPipeFd);
			close(kOutPipeFd);
			if (chdir(cwdbuf))
				fail("chdir failed");
			output_pos = output_data;
			execute_one();
			doexit(0);
		}
		int status = 0;
		uint64 start = current_time_ms();
		uint64 last_executed = start;
		uint32 executed_calls = __atomic_load_n(output_data, __ATOMIC_RELAXED);
		for (;;) {
			int res = waitpid(pid, &status, WNOHANG);
			if (res == pid)
				break;
			sleep_ms(1);
			uint64 now = current_time_ms();
			uint32 now_executed = __atomic_load_n(output_data, __ATOMIC_RELAXED);
			if (executed_calls != now_executed) {
				executed_calls = now_executed;
				last_executed = now;
			}
			if ((now - start < 3 * 1000) && (now - last_executed < 500))
				continue;
			kill(pid, SIGKILL);
			while (waitpid(pid, &status, 0) != pid) {
			}
			break;
		}
		status = WEXITSTATUS(status);
		if (status == kFailStatus)
			fail("child failed");
		if (status == kErrorStatus)
			error("child errored");
		remove_dir(cwdbuf);
		reply_execute(0);
	}
	return 0;
}

long execute_syscall(call_t* c, long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8)
{
	if (c->call)
		return c->call(a0, a1, a2, a3, a4, a5, a6, a7, a8);
	return __syscall(c->sys_nr, a0, a1, a2, a3, a4, a5, a6, a7, a8);
}

void cover_open()
{
	if (!flag_cover)
		return;
	for (int i = 0; i < kMaxThreads; i++) {
		thread_t* th = &threads[i];
#if defined(__FreeBSD__)
		th->cover_fd = open("/dev/kcov", O_RDWR);
		if (th->cover_fd == -1)
			fail("open of /dev/kcov failed");
		if (ioctl(th->cover_fd, KIOSETBUFSIZE, &kCoverSize))
			fail("ioctl init trace write failed");
		size_t mmap_alloc_size = kCoverSize * sizeof(th->cover_data[0]);
		uint64* mmap_ptr = (uint64*)mmap(NULL, mmap_alloc_size,
						 PROT_READ | PROT_WRITE,
						 MAP_SHARED, th->cover_fd, 0);
		if (mmap_ptr == NULL)
			fail("cover mmap failed");
		th->cover_size_ptr = mmap_ptr;
		th->cover_data = &mmap_ptr[1];
#else
		th->cover_data = &th->cover_buffer[0];
#endif
	}
}

void cover_enable(thread_t* th)
{
#if defined(__FreeBSD__)
	if (!flag_cover)
		return;
	debug("#%d: enabling /dev/kcov\n", th->id);
	int kcov_mode = flag_collect_comps ? KCOV_MODE_TRACE_CMP : KCOV_MODE_TRACE_PC;
	if (ioctl(th->cover_fd, KIOENABLE, &kcov_mode))
		exitf("cover enable write trace failed, mode=%d", kcov_mode);
	debug("#%d: enabled /dev/kcov\n", th->id);
#endif
}

void cover_reset(thread_t* th)
{
#if defined(__FreeBSD__)
	if (!flag_cover)
		return;

	*th->cover_size_ptr = 0;
#endif
}

uint64 read_cover_size(thread_t* th)
{
	if (!flag_cover)
		return 0;
#if defined(__FreeBSD__)
	uint64 size = *th->cover_size_ptr;
	debug("#%d: read cover size = %llu\n", th->id, size);
	if (size > kCoverSize)
		fail("#%d: too much cover %llu", th->id, size);
	return size;
#else
	// Fallback coverage since we have no real coverage available.
	// We use syscall number or-ed with returned errno value as signal.
	// At least this gives us all combinations of syscall+errno.
	th->cover_data[0] = (th->call_num << 16) | ((th->res == -1 ? th->reserrno : 0) & 0x3ff);
	return 1;
#endif
}

uint32* write_output(uint32 v)
{
	if (collide)
		return 0;
	if (output_pos < output_data || (char*)output_pos >= (char*)output_data + kMaxOutput)
		fail("output overflow");
	*output_pos = v;
	return output_pos++;
}

void write_completed(uint32 completed)
{
	__atomic_store_n(output_data, completed, __ATOMIC_RELEASE);
}

bool kcov_comparison_t::ignore() const
{
	return false;
}
<|endoftext|>


<commit_before>#pragma once

#include <iostream>

#include "RawBuffer.hpp"
#include "depthai-shared/common/Point3f.hpp"
#include "depthai-shared/common/Rect.hpp"
#include "depthai-shared/datatype/RawImgDetections.hpp"

namespace dai {

/**
 * Tracklet structure
 *
 * Contains tracklets from object tracker output.
 */
struct Tracklet {
    enum class TrackingStatus : std::int32_t {
        NEW,     /**< The object is newly added. */
        TRACKED, /**< The object is being tracked. */
        LOST /**< The object gets lost now. The object can be tracked again automatically(long term tracking) or by specifying detected object manually(short
                term and zero term tracking). */
    };
    /**
     * Tracked region of interest.
     */
    Rect roi;
    /**
     * Tracklet's ID.
     */
    std::int32_t id;
    /**
     * Tracklet's label ID.
     */
    std::int32_t label;
    /**
     * Number of frames it is being tracked for.
     */
    std::int32_t age;
    /**
     * Status of tracklet.
     */
    TrackingStatus status;

    /**
     * Image detection that is tracked.
     */
    ImgDetection srcImgDetection;
    /**
     * Spatial coordinates of tracklet.
     */
    Point3f spatialCoordinates;
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(Tracklet, roi, id, label, age, status, srcImgDetection, spatialCoordinates);
};

struct RawTracklets : public RawBuffer {
    std::vector<Tracklet> tracklets;

    void serialize(std::vector<std::uint8_t>& metadata, DatatypeEnum& datatype) override {
        nlohmann::json j = *this;
        metadata = nlohmann::json::to_msgpack(j);
        datatype = DatatypeEnum::Tracklets;
    };

    NLOHMANN_DEFINE_TYPE_INTRUSIVE(RawTracklets, tracklets);
};

}  // namespace dai
<commit_msg>Add new object tracker state: Removed<commit_after>#pragma once

#include <iostream>

#include "RawBuffer.hpp"
#include "depthai-shared/common/Point3f.hpp"
#include "depthai-shared/common/Rect.hpp"
#include "depthai-shared/datatype/RawImgDetections.hpp"

namespace dai {

/**
 * Tracklet structure
 *
 * Contains tracklets from object tracker output.
 */
struct Tracklet {
    enum class TrackingStatus : std::int32_t {
        NEW,     /**< The object is newly added. */
        TRACKED, /**< The object is being tracked. */
        LOST, /**< The object gets lost now. The object can be tracked again automatically(long term tracking) or by specifying detected object manually(short
                term and zero term tracking). */
        REMOVED /**< The object is removed. */
    };
    /**
     * Tracked region of interest.
     */
    Rect roi;
    /**
     * Tracklet's ID.
     */
    std::int32_t id;
    /**
     * Tracklet's label ID.
     */
    std::int32_t label;
    /**
     * Number of frames it is being tracked for.
     */
    std::int32_t age;
    /**
     * Status of tracklet.
     */
    TrackingStatus status;

    /**
     * Image detection that is tracked.
     */
    ImgDetection srcImgDetection;
    /**
     * Spatial coordinates of tracklet.
     */
    Point3f spatialCoordinates;
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(Tracklet, roi, id, label, age, status, srcImgDetection, spatialCoordinates);
};

struct RawTracklets : public RawBuffer {
    std::vector<Tracklet> tracklets;

    void serialize(std::vector<std::uint8_t>& metadata, DatatypeEnum& datatype) override {
        nlohmann::json j = *this;
        metadata = nlohmann::json::to_msgpack(j);
        datatype = DatatypeEnum::Tracklets;
    };

    NLOHMANN_DEFINE_TYPE_INTRUSIVE(RawTracklets, tracklets);
};

}  // namespace dai
<|endoftext|>