<commit_before>//===- InlineCost.cpp - Cost analysis for inliner -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements inline cost analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/InlineCost.h"
#include "llvm/Support/CallSite.h"
#include "llvm/CallingConv.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;

// CountCodeReductionForConstant - Figure out an approximation for how many
// instructions will be constant folded if the specified value is constant.
//
unsigned InlineCostAnalyzer::FunctionInfo::
         CountCodeReductionForConstant(Value *V) {
  unsigned Reduction = 0;
  for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI)
    if (isa<BranchInst>(*UI))
      Reduction += 40;          // Eliminating a conditional branch is a big win
    else if (SwitchInst *SI = dyn_cast<SwitchInst>(*UI))
      // Eliminating a switch is a big win, proportional to the number of edges
      // deleted.
      Reduction += (SI->getNumSuccessors()-1) * 40;
    else if (CallInst *CI = dyn_cast<CallInst>(*UI)) {
      // Turning an indirect call into a direct call is a BIG win
      Reduction += CI->getCalledValue() == V ? 500 : 0;
    } else if (InvokeInst *II = dyn_cast<InvokeInst>(*UI)) {
      // Turning an indirect call into a direct call is a BIG win
      Reduction += II->getCalledValue() == V ? 500 : 0;
    } else {
      // Figure out if this instruction will be removed due to simple constant
      // propagation.
      Instruction &Inst = cast<Instruction>(**UI);

      // We can't constant propagate instructions which have effects or
      // read memory.
      //
      // FIXME: It would be nice to capture the fact that a load from a
      // pointer-to-constant-global is actually a *really* good thing to zap.
      // Unfortunately, we don't know the pointer that may get propagated here,
      // so we can't make this decision.
      if (Inst.mayReadFromMemory() || Inst.mayHaveSideEffects() ||
          isa<AllocationInst>(Inst))
        continue;

      bool AllOperandsConstant = true;
      for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i)
        if (!isa<Constant>(Inst.getOperand(i)) && Inst.getOperand(i) != V) {
          AllOperandsConstant = false;
          break;
        }

      if (AllOperandsConstant) {
        // We will get to remove this instruction...
        Reduction += 7;

        // And any other instructions that use it which become constants
        // themselves.
        Reduction += CountCodeReductionForConstant(&Inst);
      }
    }

  return Reduction;
}

// CountCodeReductionForAlloca - Figure out an approximation of how much smaller
// the function will be if it is inlined into a context where an argument
// becomes an alloca.
//
unsigned InlineCostAnalyzer::FunctionInfo::
         CountCodeReductionForAlloca(Value *V) {
  if (!isa<PointerType>(V->getType())) return 0;  // Not a pointer
  unsigned Reduction = 0;
  for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){
    Instruction *I = cast<Instruction>(*UI);
    if (isa<LoadInst>(I) || isa<StoreInst>(I))
      Reduction += 10;
    else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I)) {
      // If the GEP has variable indices, we won't be able to do much with it.
      if (!GEP->hasAllConstantIndices())
        Reduction += CountCodeReductionForAlloca(GEP)+15;
    } else {
      // If there is some other strange instruction, we're not going to be able
      // to do much if we inline this.
      return 0;
    }
  }

  return Reduction;
}

/// analyzeFunction - Fill in the current structure with information gleaned
/// from the specified function.
void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) {
  unsigned NumInsts = 0, NumBlocks = 0, NumVectorInsts = 0, NumRets = 0;

  // Look at the size of the callee.  Each basic block counts as 20 units, and
  // each instruction counts as 5.
  for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
    for (BasicBlock::const_iterator II = BB->begin(), E = BB->end();
         II != E; ++II) {
      if (isa<PHINode>(II)) continue;           // PHI nodes don't count.

      // Special handling for calls.
      if (isa<CallInst>(II) || isa<InvokeInst>(II)) {
        if (isa<DbgInfoIntrinsic>(II))
          continue;  // Debug intrinsics don't count as size.

        CallSite CS = CallSite::get(const_cast<Instruction*>(&*II));

        // If this function contains a call to setjmp or _setjmp, never inline
        // it.  This is a hack because we depend on the user marking their local
        // variables as volatile if they are live across a setjmp call, and they
        // probably won't do this in callers.
        if (Function *F = CS.getCalledFunction())
          if (F->isDeclaration() &&
              (F->getName() == "setjmp" || F->getName() == "_setjmp")) {
            NeverInline = true;
            return;
          }

        // Calls often compile into many machine instructions.  Bump up their
        // cost to reflect this.
        if (!isa<IntrinsicInst>(II))
          NumInsts += 5;
      }

      // This, too, is a call.
      if (isa<MallocInst>(II))
	NumInsts += 5;

      if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
        if (!AI->isStaticAlloca())
          this->usesDynamicAlloca = true;
      }

      if (isa<ExtractElementInst>(II) || isa<VectorType>(II->getType()))
        ++NumVectorInsts;

      // Noop casts, including ptr <-> int,  don't count.
      if (const CastInst *CI = dyn_cast<CastInst>(II)) {
        if (CI->isLosslessCast() || isa<IntToPtrInst>(CI) ||
            isa<PtrToIntInst>(CI))
          continue;
      } else if (const GetElementPtrInst *GEPI =
                 dyn_cast<GetElementPtrInst>(II)) {
        // If a GEP has all constant indices, it will probably be folded with
        // a load/store.
        if (GEPI->hasAllConstantIndices())
          continue;
      }

      if (isa<ReturnInst>(II))
        ++NumRets;

      ++NumInsts;
    }

    ++NumBlocks;
  }

  // A function with exactly one return has it removed during the inlining
  // process (see InlineFunction), so don't count it.
  if (NumRets==1)
    --NumInsts;

  this->NumBlocks      = NumBlocks;
  this->NumInsts       = NumInsts;
  this->NumVectorInsts = NumVectorInsts;

  // Check out all of the arguments to the function, figuring out how much
  // code can be eliminated if one of the arguments is a constant.
  for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
    ArgumentWeights.push_back(ArgInfo(CountCodeReductionForConstant(I),
                                      CountCodeReductionForAlloca(I)));
}

// getInlineCost - The heuristic used to determine if we should inline the
// function call or not.
//
InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
                               SmallPtrSet<const Function *, 16> &NeverInline) {
  Instruction *TheCall = CS.getInstruction();
  Function *Callee = CS.getCalledFunction();
  Function *Caller = TheCall->getParent()->getParent();

  // Don't inline functions which can be redefined at link-time to mean
  // something else.  Don't inline functions marked noinline.
  if (Callee->mayBeOverridden() ||
      Callee->hasFnAttr(Attribute::NoInline) || NeverInline.count(Callee))
    return llvm::InlineCost::getNever();

  // InlineCost - This value measures how good of an inline candidate this call
  // site is to inline.  A lower inline cost make is more likely for the call to
  // be inlined.  This value may go negative.
  //
  int InlineCost = 0;

  // If there is only one call of the function, and it has internal linkage,
  // make it almost guaranteed to be inlined.
  //
  if (Callee->hasLocalLinkage() && Callee->hasOneUse())
    InlineCost -= 15000;

  // If this function uses the coldcc calling convention, prefer not to inline
  // it.
  if (Callee->getCallingConv() == CallingConv::Cold)
    InlineCost += 2000;

  // If the instruction after the call, or if the normal destination of the
  // invoke is an unreachable instruction, the function is noreturn.  As such,
  // there is little point in inlining this.
  if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
    if (isa<UnreachableInst>(II->getNormalDest()->begin()))
      InlineCost += 10000;
  } else if (isa<UnreachableInst>(++BasicBlock::iterator(TheCall)))
    InlineCost += 10000;

  // Get information about the callee...
  FunctionInfo &CalleeFI = CachedFunctionInfo[Callee];

  // If we haven't calculated this information yet, do so now.
  if (CalleeFI.NumBlocks == 0)
    CalleeFI.analyzeFunction(Callee);

  // If we should never inline this, return a huge cost.
  if (CalleeFI.NeverInline)
    return InlineCost::getNever();

  // FIXME: It would be nice to kill off CalleeFI.NeverInline. Then we
  // could move this up and avoid computing the FunctionInfo for
  // things we are going to just return always inline for. This
  // requires handling setjmp somewhere else, however.
  if (!Callee->isDeclaration() && Callee->hasFnAttr(Attribute::AlwaysInline))
    return InlineCost::getAlways();

  if (CalleeFI.usesDynamicAlloca) {
    // Get infomation about the caller...
    FunctionInfo &CallerFI = CachedFunctionInfo[Caller];

    // If we haven't calculated this information yet, do so now.
    if (CallerFI.NumBlocks == 0)
      CallerFI.analyzeFunction(Caller);

    // Don't inline a callee with dynamic alloca into a caller without them.
    // Functions containing dynamic alloca's are inefficient in various ways;
    // don't create more inefficiency.
    if (!CallerFI.usesDynamicAlloca)
      return InlineCost::getNever();
  }

  // Add to the inline quality for properties that make the call valuable to
  // inline.  This includes factors that indicate that the result of inlining
  // the function will be optimizable.  Currently this just looks at arguments
  // passed into the function.
  //
  unsigned ArgNo = 0;
  for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
       I != E; ++I, ++ArgNo) {
    // Each argument passed in has a cost at both the caller and the callee
    // sides.  This favors functions that take many arguments over functions
    // that take few arguments.
    InlineCost -= 20;

    // If this is a function being passed in, it is very likely that we will be
    // able to turn an indirect function call into a direct function call.
    if (isa<Function>(I))
      InlineCost -= 100;

    // If an alloca is passed in, inlining this function is likely to allow
    // significant future optimization possibilities (like scalar promotion, and
    // scalarization), so encourage the inlining of the function.
    //
    else if (isa<AllocaInst>(I)) {
      if (ArgNo < CalleeFI.ArgumentWeights.size())
        InlineCost -= CalleeFI.ArgumentWeights[ArgNo].AllocaWeight;

      // If this is a constant being passed into the function, use the argument
      // weights calculated for the callee to determine how much will be folded
      // away with this information.
    } else if (isa<Constant>(I)) {
      if (ArgNo < CalleeFI.ArgumentWeights.size())
        InlineCost -= CalleeFI.ArgumentWeights[ArgNo].ConstantWeight;
    }
  }

  // Now that we have considered all of the factors that make the call site more
  // likely to be inlined, look at factors that make us not want to inline it.

  // Don't inline into something too big, which would make it bigger.
  // "size" here is the number of basic blocks, not instructions.
  //
  InlineCost += Caller->size()/15;

  // Look at the size of the callee. Each instruction counts as 5.
  InlineCost += CalleeFI.NumInsts*5;

  return llvm::InlineCost::get(InlineCost);
}

// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a
// higher threshold to determine if the function call should be inlined.
float InlineCostAnalyzer::getInlineFudgeFactor(CallSite CS) {
  Function *Callee = CS.getCalledFunction();

  // Get information about the callee...
  FunctionInfo &CalleeFI = CachedFunctionInfo[Callee];

  // If we haven't calculated this information yet, do so now.
  if (CalleeFI.NumBlocks == 0)
    CalleeFI.analyzeFunction(Callee);

  float Factor = 1.0f;
  // Single BB functions are often written to be inlined.
  if (CalleeFI.NumBlocks == 1)
    Factor += 0.5f;

  // Be more aggressive if the function contains a good chunk (if it mades up
  // at least 10% of the instructions) of vector instructions.
  if (CalleeFI.NumVectorInsts > CalleeFI.NumInsts/2)
    Factor += 2.0f;
  else if (CalleeFI.NumVectorInsts > CalleeFI.NumInsts/10)
    Factor += 1.5f;
  return Factor;
}
<commit_msg>Add FreeInst to the "is a call" check for Insts that are calls, but not intrinsics.<commit_after>//===- InlineCost.cpp - Cost analysis for inliner -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements inline cost analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/InlineCost.h"
#include "llvm/Support/CallSite.h"
#include "llvm/CallingConv.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;

// CountCodeReductionForConstant - Figure out an approximation for how many
// instructions will be constant folded if the specified value is constant.
//
unsigned InlineCostAnalyzer::FunctionInfo::
         CountCodeReductionForConstant(Value *V) {
  unsigned Reduction = 0;
  for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI)
    if (isa<BranchInst>(*UI))
      Reduction += 40;          // Eliminating a conditional branch is a big win
    else if (SwitchInst *SI = dyn_cast<SwitchInst>(*UI))
      // Eliminating a switch is a big win, proportional to the number of edges
      // deleted.
      Reduction += (SI->getNumSuccessors()-1) * 40;
    else if (CallInst *CI = dyn_cast<CallInst>(*UI)) {
      // Turning an indirect call into a direct call is a BIG win
      Reduction += CI->getCalledValue() == V ? 500 : 0;
    } else if (InvokeInst *II = dyn_cast<InvokeInst>(*UI)) {
      // Turning an indirect call into a direct call is a BIG win
      Reduction += II->getCalledValue() == V ? 500 : 0;
    } else {
      // Figure out if this instruction will be removed due to simple constant
      // propagation.
      Instruction &Inst = cast<Instruction>(**UI);

      // We can't constant propagate instructions which have effects or
      // read memory.
      //
      // FIXME: It would be nice to capture the fact that a load from a
      // pointer-to-constant-global is actually a *really* good thing to zap.
      // Unfortunately, we don't know the pointer that may get propagated here,
      // so we can't make this decision.
      if (Inst.mayReadFromMemory() || Inst.mayHaveSideEffects() ||
          isa<AllocationInst>(Inst))
        continue;

      bool AllOperandsConstant = true;
      for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i)
        if (!isa<Constant>(Inst.getOperand(i)) && Inst.getOperand(i) != V) {
          AllOperandsConstant = false;
          break;
        }

      if (AllOperandsConstant) {
        // We will get to remove this instruction...
        Reduction += 7;

        // And any other instructions that use it which become constants
        // themselves.
        Reduction += CountCodeReductionForConstant(&Inst);
      }
    }

  return Reduction;
}

// CountCodeReductionForAlloca - Figure out an approximation of how much smaller
// the function will be if it is inlined into a context where an argument
// becomes an alloca.
//
unsigned InlineCostAnalyzer::FunctionInfo::
         CountCodeReductionForAlloca(Value *V) {
  if (!isa<PointerType>(V->getType())) return 0;  // Not a pointer
  unsigned Reduction = 0;
  for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){
    Instruction *I = cast<Instruction>(*UI);
    if (isa<LoadInst>(I) || isa<StoreInst>(I))
      Reduction += 10;
    else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I)) {
      // If the GEP has variable indices, we won't be able to do much with it.
      if (!GEP->hasAllConstantIndices())
        Reduction += CountCodeReductionForAlloca(GEP)+15;
    } else {
      // If there is some other strange instruction, we're not going to be able
      // to do much if we inline this.
      return 0;
    }
  }

  return Reduction;
}

/// analyzeFunction - Fill in the current structure with information gleaned
/// from the specified function.
void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) {
  unsigned NumInsts = 0, NumBlocks = 0, NumVectorInsts = 0, NumRets = 0;

  // Look at the size of the callee.  Each basic block counts as 20 units, and
  // each instruction counts as 5.
  for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
    for (BasicBlock::const_iterator II = BB->begin(), E = BB->end();
         II != E; ++II) {
      if (isa<PHINode>(II)) continue;           // PHI nodes don't count.

      // Special handling for calls.
      if (isa<CallInst>(II) || isa<InvokeInst>(II)) {
        if (isa<DbgInfoIntrinsic>(II))
          continue;  // Debug intrinsics don't count as size.

        CallSite CS = CallSite::get(const_cast<Instruction*>(&*II));

        // If this function contains a call to setjmp or _setjmp, never inline
        // it.  This is a hack because we depend on the user marking their local
        // variables as volatile if they are live across a setjmp call, and they
        // probably won't do this in callers.
        if (Function *F = CS.getCalledFunction())
          if (F->isDeclaration() &&
              (F->getName() == "setjmp" || F->getName() == "_setjmp")) {
            NeverInline = true;
            return;
          }

        // Calls often compile into many machine instructions.  Bump up their
        // cost to reflect this.
        if (!isa<IntrinsicInst>(II))
          NumInsts += 5;
      }

      // These, too, are calls.
      if (isa<MallocInst>(II) || isa<FreeInst>(II))
	NumInsts += 5;

      if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
        if (!AI->isStaticAlloca())
          this->usesDynamicAlloca = true;
      }

      if (isa<ExtractElementInst>(II) || isa<VectorType>(II->getType()))
        ++NumVectorInsts;

      // Noop casts, including ptr <-> int,  don't count.
      if (const CastInst *CI = dyn_cast<CastInst>(II)) {
        if (CI->isLosslessCast() || isa<IntToPtrInst>(CI) ||
            isa<PtrToIntInst>(CI))
          continue;
      } else if (const GetElementPtrInst *GEPI =
                 dyn_cast<GetElementPtrInst>(II)) {
        // If a GEP has all constant indices, it will probably be folded with
        // a load/store.
        if (GEPI->hasAllConstantIndices())
          continue;
      }

      if (isa<ReturnInst>(II))
        ++NumRets;

      ++NumInsts;
    }

    ++NumBlocks;
  }

  // A function with exactly one return has it removed during the inlining
  // process (see InlineFunction), so don't count it.
  if (NumRets==1)
    --NumInsts;

  this->NumBlocks      = NumBlocks;
  this->NumInsts       = NumInsts;
  this->NumVectorInsts = NumVectorInsts;

  // Check out all of the arguments to the function, figuring out how much
  // code can be eliminated if one of the arguments is a constant.
  for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
    ArgumentWeights.push_back(ArgInfo(CountCodeReductionForConstant(I),
                                      CountCodeReductionForAlloca(I)));
}

// getInlineCost - The heuristic used to determine if we should inline the
// function call or not.
//
InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
                               SmallPtrSet<const Function *, 16> &NeverInline) {
  Instruction *TheCall = CS.getInstruction();
  Function *Callee = CS.getCalledFunction();
  Function *Caller = TheCall->getParent()->getParent();

  // Don't inline functions which can be redefined at link-time to mean
  // something else.  Don't inline functions marked noinline.
  if (Callee->mayBeOverridden() ||
      Callee->hasFnAttr(Attribute::NoInline) || NeverInline.count(Callee))
    return llvm::InlineCost::getNever();

  // InlineCost - This value measures how good of an inline candidate this call
  // site is to inline.  A lower inline cost make is more likely for the call to
  // be inlined.  This value may go negative.
  //
  int InlineCost = 0;

  // If there is only one call of the function, and it has internal linkage,
  // make it almost guaranteed to be inlined.
  //
  if (Callee->hasLocalLinkage() && Callee->hasOneUse())
    InlineCost -= 15000;

  // If this function uses the coldcc calling convention, prefer not to inline
  // it.
  if (Callee->getCallingConv() == CallingConv::Cold)
    InlineCost += 2000;

  // If the instruction after the call, or if the normal destination of the
  // invoke is an unreachable instruction, the function is noreturn.  As such,
  // there is little point in inlining this.
  if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
    if (isa<UnreachableInst>(II->getNormalDest()->begin()))
      InlineCost += 10000;
  } else if (isa<UnreachableInst>(++BasicBlock::iterator(TheCall)))
    InlineCost += 10000;

  // Get information about the callee...
  FunctionInfo &CalleeFI = CachedFunctionInfo[Callee];

  // If we haven't calculated this information yet, do so now.
  if (CalleeFI.NumBlocks == 0)
    CalleeFI.analyzeFunction(Callee);

  // If we should never inline this, return a huge cost.
  if (CalleeFI.NeverInline)
    return InlineCost::getNever();

  // FIXME: It would be nice to kill off CalleeFI.NeverInline. Then we
  // could move this up and avoid computing the FunctionInfo for
  // things we are going to just return always inline for. This
  // requires handling setjmp somewhere else, however.
  if (!Callee->isDeclaration() && Callee->hasFnAttr(Attribute::AlwaysInline))
    return InlineCost::getAlways();

  if (CalleeFI.usesDynamicAlloca) {
    // Get infomation about the caller...
    FunctionInfo &CallerFI = CachedFunctionInfo[Caller];

    // If we haven't calculated this information yet, do so now.
    if (CallerFI.NumBlocks == 0)
      CallerFI.analyzeFunction(Caller);

    // Don't inline a callee with dynamic alloca into a caller without them.
    // Functions containing dynamic alloca's are inefficient in various ways;
    // don't create more inefficiency.
    if (!CallerFI.usesDynamicAlloca)
      return InlineCost::getNever();
  }

  // Add to the inline quality for properties that make the call valuable to
  // inline.  This includes factors that indicate that the result of inlining
  // the function will be optimizable.  Currently this just looks at arguments
  // passed into the function.
  //
  unsigned ArgNo = 0;
  for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
       I != E; ++I, ++ArgNo) {
    // Each argument passed in has a cost at both the caller and the callee
    // sides.  This favors functions that take many arguments over functions
    // that take few arguments.
    InlineCost -= 20;

    // If this is a function being passed in, it is very likely that we will be
    // able to turn an indirect function call into a direct function call.
    if (isa<Function>(I))
      InlineCost -= 100;

    // If an alloca is passed in, inlining this function is likely to allow
    // significant future optimization possibilities (like scalar promotion, and
    // scalarization), so encourage the inlining of the function.
    //
    else if (isa<AllocaInst>(I)) {
      if (ArgNo < CalleeFI.ArgumentWeights.size())
        InlineCost -= CalleeFI.ArgumentWeights[ArgNo].AllocaWeight;

      // If this is a constant being passed into the function, use the argument
      // weights calculated for the callee to determine how much will be folded
      // away with this information.
    } else if (isa<Constant>(I)) {
      if (ArgNo < CalleeFI.ArgumentWeights.size())
        InlineCost -= CalleeFI.ArgumentWeights[ArgNo].ConstantWeight;
    }
  }

  // Now that we have considered all of the factors that make the call site more
  // likely to be inlined, look at factors that make us not want to inline it.

  // Don't inline into something too big, which would make it bigger.
  // "size" here is the number of basic blocks, not instructions.
  //
  InlineCost += Caller->size()/15;

  // Look at the size of the callee. Each instruction counts as 5.
  InlineCost += CalleeFI.NumInsts*5;

  return llvm::InlineCost::get(InlineCost);
}

// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a
// higher threshold to determine if the function call should be inlined.
float InlineCostAnalyzer::getInlineFudgeFactor(CallSite CS) {
  Function *Callee = CS.getCalledFunction();

  // Get information about the callee...
  FunctionInfo &CalleeFI = CachedFunctionInfo[Callee];

  // If we haven't calculated this information yet, do so now.
  if (CalleeFI.NumBlocks == 0)
    CalleeFI.analyzeFunction(Callee);

  float Factor = 1.0f;
  // Single BB functions are often written to be inlined.
  if (CalleeFI.NumBlocks == 1)
    Factor += 0.5f;

  // Be more aggressive if the function contains a good chunk (if it mades up
  // at least 10% of the instructions) of vector instructions.
  if (CalleeFI.NumVectorInsts > CalleeFI.NumInsts/2)
    Factor += 2.0f;
  else if (CalleeFI.NumVectorInsts > CalleeFI.NumInsts/10)
    Factor += 1.5f;
  return Factor;
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "cling/UserInterface/UserInterface.h"

#include "cling/Interpreter/StoredValueRef.h"
#include "cling/MetaProcessor/MetaProcessor.h"
#include "textinput/TextInput.h"
#include "textinput/StreamReader.h"
#include "textinput/TerminalDisplay.h"

#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/PathV1.h"
#include "llvm/Config/config.h"

// Fragment copied from LLVM's raw_ostream.cpp
#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#endif

#if defined(_MSC_VER)
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
# define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
# define STDERR_FILENO 2
#endif
#endif

namespace cling {
  UserInterface::UserInterface(Interpreter& interp) {
    // We need stream that doesn't close its file descriptor, thus we are not
    // using llvm::outs. Keeping file descriptor open we will be able to use
    // the results in pipes (Savannah #99234).
    static llvm::raw_fd_ostream m_MPOuts (STDOUT_FILENO, /*ShouldClose*/false);
    m_MetaProcessor.reset(new MetaProcessor(interp, m_MPOuts));
  }

  UserInterface::~UserInterface() {}

  void UserInterface::runInteractively(bool nologo /* = false */) {
    if (!nologo) {
      PrintLogo();
    }

    // History file is $HOME/.cling_history
    static const char* histfile = ".cling_history";
    llvm::sys::Path histfilePath = llvm::sys::Path::GetUserHomeDirectory();
    histfilePath.appendComponent(histfile);

    using namespace textinput;
    StreamReader* R = StreamReader::Create();
    TerminalDisplay* D = TerminalDisplay::Create();
    TextInput TI(*R, *D, histfilePath.c_str());

    TI.SetPrompt("[cling]$ ");
    std::string line;

    while (true) {
      m_MetaProcessor->getOuts().flush();
      TextInput::EReadResult RR = TI.ReadInput();
      TI.TakeInput(line);
      if (RR == TextInput::kRREOF) {
        break;
      }

      cling::Interpreter::CompilationResult compRes;
      int indent = m_MetaProcessor->process(line.c_str(), compRes, 0/*result*/);
      // Quit requested
      if (indent < 0)
        break;
      std::string Prompt = "[cling]";
      if (m_MetaProcessor->getInterpreter().isRawInputEnabled())
        Prompt.append("! ");
      else
        Prompt.append("$ ");

      if (indent > 0)
        // Continuation requested.
        Prompt.append('?' + std::string(indent * 3, ' '));

      TI.SetPrompt(Prompt.c_str());

    }
  }

  void UserInterface::PrintLogo() {
    llvm::raw_ostream& outs = m_MetaProcessor->getOuts();
    outs << "\n";
    outs << "****************** CLING ******************" << "\n";
    outs << "* Type C++ code and press enter to run it *" << "\n";
    outs << "*             Type .q to exit             *" << "\n";
    outs << "*******************************************" << "\n";
  }
} // end namespace cling
<commit_msg>Try to handle exceptions coming from the JIT.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "cling/UserInterface/UserInterface.h"

#include "cling/Interpreter/StoredValueRef.h"
#include "cling/MetaProcessor/MetaProcessor.h"
#include "textinput/TextInput.h"
#include "textinput/StreamReader.h"
#include "textinput/TerminalDisplay.h"

#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/PathV1.h"
#include "llvm/Config/config.h"

// Fragment copied from LLVM's raw_ostream.cpp
#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#endif

#if defined(_MSC_VER)
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
# define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
# define STDERR_FILENO 2
#endif
#endif

namespace cling {
  UserInterface::UserInterface(Interpreter& interp) {
    // We need stream that doesn't close its file descriptor, thus we are not
    // using llvm::outs. Keeping file descriptor open we will be able to use
    // the results in pipes (Savannah #99234).
    static llvm::raw_fd_ostream m_MPOuts (STDOUT_FILENO, /*ShouldClose*/false);
    m_MetaProcessor.reset(new MetaProcessor(interp, m_MPOuts));
  }

  UserInterface::~UserInterface() {}

  void UserInterface::runInteractively(bool nologo /* = false */) {
    if (!nologo) {
      PrintLogo();
    }

    // History file is $HOME/.cling_history
    static const char* histfile = ".cling_history";
    llvm::sys::Path histfilePath = llvm::sys::Path::GetUserHomeDirectory();
    histfilePath.appendComponent(histfile);

    using namespace textinput;
    StreamReader* R = StreamReader::Create();
    TerminalDisplay* D = TerminalDisplay::Create();
    TextInput TI(*R, *D, histfilePath.c_str());

    TI.SetPrompt("[cling]$ ");
    std::string line;
    try {
      while (true) {
        m_MetaProcessor->getOuts().flush();
        TextInput::EReadResult RR = TI.ReadInput();
        TI.TakeInput(line);
        if (RR == TextInput::kRREOF) {
          break;
        }

        cling::Interpreter::CompilationResult compRes;
        int indent
          = m_MetaProcessor->process(line.c_str(), compRes, 0/*result*/);
        // Quit requested
        if (indent < 0)
          break;
        std::string Prompt = "[cling]";
        if (m_MetaProcessor->getInterpreter().isRawInputEnabled())
          Prompt.append("! ");
        else
          Prompt.append("$ ");

        if (indent > 0)
          // Continuation requested.
          Prompt.append('?' + std::string(indent * 3, ' '));

        TI.SetPrompt(Prompt.c_str());

      }
    }
    catch() {
      llvm::errs() << "Exception occurred. Recovering...\n";
    }
  }

  void UserInterface::PrintLogo() {
    llvm::raw_ostream& outs = m_MetaProcessor->getOuts();
    outs << "\n";
    outs << "****************** CLING ******************" << "\n";
    outs << "* Type C++ code and press enter to run it *" << "\n";
    outs << "*             Type .q to exit             *" << "\n";
    outs << "*******************************************" << "\n";
  }
} // end namespace cling
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "fnord-base/io/filerepository.h"
#include "fnord-base/io/fileutil.h"
#include "fnord-base/application.h"
#include "fnord-base/logging.h"
#include "fnord-base/random.h"
#include "fnord-base/thread/eventloop.h"
#include "fnord-base/thread/threadpool.h"
#include "fnord-base/wallclock.h"
#include "fnord-base/VFS.h"
#include "fnord-rpc/ServerGroup.h"
#include "fnord-rpc/RPC.h"
#include "fnord-rpc/RPCClient.h"
#include "fnord-base/cli/flagparser.h"
#include "fnord-json/json.h"
#include "fnord-json/jsonrpc.h"
#include "fnord-http/httprouter.h"
#include "fnord-http/httpserver.h"
#include "fnord-http/VFSFileServlet.h"
#include "fnord-feeds/FeedService.h"
#include "fnord-feeds/RemoteFeedFactory.h"
#include "fnord-feeds/RemoteFeedReader.h"
#include "fnord-base/stats/statsdagent.h"
#include "fnord-sstable/SSTableServlet.h"
#include "fnord-mdb/MDB.h"
#include "fnord-mdb/MDBUtil.h"
#include "common.h"
#include "CustomerNamespace.h"
#include "FeatureSchema.h"
#include "JoinedQuery.h"
#include "analytics/AnalyticsServlet.h"
#include "analytics/CTRByPageServlet.h"
#include "analytics/CTRStatsServlet.h"
#include "analytics/CTRByPositionQuery.h"
#include "analytics/CTRByPageQuery.h"
#include "analytics/DiscoveryKPIQuery.h"
#include "analytics/DiscoveryCategoryStatsQuery.h"
#include "analytics/AnalyticsQueryEngine.h"

using namespace fnord;

int main(int argc, const char** argv) {
  fnord::Application::init();
  fnord::Application::logToStderr();

  fnord::cli::FlagParser flags;

  flags.defineFlag(
      "http_port",
      fnord::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8000",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "artifacts",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "artifacts path",
      "<path>");

  flags.defineFlag(
      "loglevel",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  WhitelistVFS vfs;

  /* start http server */
  fnord::thread::EventLoop ev;
  fnord::thread::ThreadPool tpool;
  fnord::http::HTTPRouter http_router;
  fnord::http::HTTPServer http_server(&http_router, &ev);
  http_server.listen(flags.getInt("http_port"));

  /* sstable servlet */
  sstable::SSTableServlet sstable_servlet("/sstable", &vfs);
  http_router.addRouteByPrefixMatch("/sstable", &sstable_servlet);

  /* file servlet */
  http::VFSFileServlet file_servlet("/file", &vfs);
  http_router.addRouteByPrefixMatch("/file", &file_servlet);

  /* add all files to whitelist vfs */
  auto dir = flags.getString("artifacts");
  FileUtil::ls(dir, [&vfs, &dir] (const String& file) -> bool {
    vfs.registerFile(file, FileUtil::joinPaths(dir, file));
    fnord::logInfo("cm.reportserver", "[VFS] Adding file: $0", file);
    return true;
  });

  /* analytics */
  cm::AnalyticsQueryEngine analytics(8, &vfs);
  cm::AnalyticsServlet analytics_servlet(&analytics);
  http_router.addRouteByPrefixMatch("/analytics", &analytics_servlet, &tpool);

  analytics.registerQueryFactory("ctr_by_position", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::CTRByPositionQuery(scan, segments);
  });

  analytics.registerQueryFactory("ctr_by_page", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::CTRByPageQuery(scan, segments);
  });

  analytics.registerQueryFactory("discovery_kpis", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryKPIQuery(scan, segments);
  });

  analytics.registerQueryFactory("discovery_category0_kpis", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        "queries.category1",
        "queries.category1",
        params);
  });

  analytics.registerQueryFactory("discovery_category1_kpis", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        "queries.category1",
        "queries.category2",
        params);
  });

  analytics.registerQueryFactory("discovery_category2_kpis", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        "queries.category2",
        "queries.category3",
        params);
  });

  analytics.registerQueryFactory("discovery_category3_kpis", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        "queries.category3",
        "queries.category3",
        params);
  });

  ev.run();
  return 0;
}

<commit_msg>honour time range in DiscoveryKPIQuery<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "fnord-base/io/filerepository.h"
#include "fnord-base/io/fileutil.h"
#include "fnord-base/application.h"
#include "fnord-base/logging.h"
#include "fnord-base/random.h"
#include "fnord-base/thread/eventloop.h"
#include "fnord-base/thread/threadpool.h"
#include "fnord-base/wallclock.h"
#include "fnord-base/VFS.h"
#include "fnord-rpc/ServerGroup.h"
#include "fnord-rpc/RPC.h"
#include "fnord-rpc/RPCClient.h"
#include "fnord-base/cli/flagparser.h"
#include "fnord-json/json.h"
#include "fnord-json/jsonrpc.h"
#include "fnord-http/httprouter.h"
#include "fnord-http/httpserver.h"
#include "fnord-http/VFSFileServlet.h"
#include "fnord-feeds/FeedService.h"
#include "fnord-feeds/RemoteFeedFactory.h"
#include "fnord-feeds/RemoteFeedReader.h"
#include "fnord-base/stats/statsdagent.h"
#include "fnord-sstable/SSTableServlet.h"
#include "fnord-mdb/MDB.h"
#include "fnord-mdb/MDBUtil.h"
#include "common.h"
#include "CustomerNamespace.h"
#include "FeatureSchema.h"
#include "JoinedQuery.h"
#include "analytics/AnalyticsServlet.h"
#include "analytics/CTRByPageServlet.h"
#include "analytics/CTRStatsServlet.h"
#include "analytics/CTRByPositionQuery.h"
#include "analytics/CTRByPageQuery.h"
#include "analytics/DiscoveryKPIQuery.h"
#include "analytics/DiscoveryCategoryStatsQuery.h"
#include "analytics/AnalyticsQueryEngine.h"

using namespace fnord;

int main(int argc, const char** argv) {
  fnord::Application::init();
  fnord::Application::logToStderr();

  fnord::cli::FlagParser flags;

  flags.defineFlag(
      "http_port",
      fnord::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8000",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "artifacts",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "artifacts path",
      "<path>");

  flags.defineFlag(
      "loglevel",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  WhitelistVFS vfs;

  /* start http server */
  fnord::thread::EventLoop ev;
  fnord::thread::ThreadPool tpool;
  fnord::http::HTTPRouter http_router;
  fnord::http::HTTPServer http_server(&http_router, &ev);
  http_server.listen(flags.getInt("http_port"));

  /* sstable servlet */
  sstable::SSTableServlet sstable_servlet("/sstable", &vfs);
  http_router.addRouteByPrefixMatch("/sstable", &sstable_servlet);

  /* file servlet */
  http::VFSFileServlet file_servlet("/file", &vfs);
  http_router.addRouteByPrefixMatch("/file", &file_servlet);

  /* add all files to whitelist vfs */
  auto dir = flags.getString("artifacts");
  FileUtil::ls(dir, [&vfs, &dir] (const String& file) -> bool {
    vfs.registerFile(file, FileUtil::joinPaths(dir, file));
    fnord::logInfo("cm.reportserver", "[VFS] Adding file: $0", file);
    return true;
  });

  /* analytics */
  cm::AnalyticsQueryEngine analytics(8, &vfs);
  cm::AnalyticsServlet analytics_servlet(&analytics);
  http_router.addRouteByPrefixMatch("/analytics", &analytics_servlet, &tpool);

  analytics.registerQueryFactory("ctr_by_position", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::CTRByPositionQuery(scan, segments);
  });

  analytics.registerQueryFactory("ctr_by_page", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::CTRByPageQuery(scan, segments);
  });

  analytics.registerQueryFactory("discovery_kpis", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryKPIQuery(
        scan,
        segments,
        query.start_time,
        query.end_time);
  });

  analytics.registerQueryFactory("discovery_category0_kpis", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        "queries.category1",
        "queries.category1",
        params);
  });

  analytics.registerQueryFactory("discovery_category1_kpis", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        "queries.category1",
        "queries.category2",
        params);
  });

  analytics.registerQueryFactory("discovery_category2_kpis", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        "queries.category2",
        "queries.category3",
        params);
  });

  analytics.registerQueryFactory("discovery_category3_kpis", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        "queries.category3",
        "queries.category3",
        params);
  });

  ev.run();
  return 0;
}

<|endoftext|>


<commit_before>// Copyright (c) 2014-2015 The Dash developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "coinbase-payee.h"
#include "util.h"
#include "addrman.h"
#include "masternode.h"
#include "darksend.h"
#include "masternodeman.h"
#include <boost/filesystem.hpp>

CCoinbasePayee coinbasePayee;

//
// CCoinbasePayeeDB
//

CCoinbasePayeeDB::CCoinbasePayeeDB()
{
    pathDB = GetDataDir() / "coinbase-payee.dat";
    strMagicMessage = "CoinbasePayeeDB";
}

bool CCoinbasePayeeDB::Write(const CCoinbasePayee& objToSave)
{
    int64_t nStart = GetTimeMillis();

    // serialize, checksum data up to that point, then append checksum
    CDataStream ssObj(SER_DISK, CLIENT_VERSION);
    ssObj << strMagicMessage; // coinbase payee cache file specific magic message
    ssObj << FLATDATA(Params().MessageStart()); // network specific magic number
    ssObj << objToSave;
    uint256 hash = Hash(ssObj.begin(), ssObj.end());
    ssObj << hash;

    // open output file, and associate with CAutoFile
    FILE *file = fopen(pathDB.string().c_str(), "wb");
    CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
    if (fileout.IsNull())
        return error("%s : Failed to open file %s", __func__, pathDB.string());

    // Write and commit header, data
    try {
        fileout << ssObj;
    }
    catch (std::exception &e) {
        return error("%s : Serialize or I/O error - %s", __func__, e.what());
    }
    fileout.fclose();

    LogPrintf("Written info to coinbase-payee.dat  %dms\n", GetTimeMillis() - nStart);

    return true;
}

CCoinbasePayeeDB::ReadResult CCoinbasePayeeDB::Read(CCoinbasePayee& objToLoad)
{

    int64_t nStart = GetTimeMillis();
    // open input file, and associate with CAutoFile
    FILE *file = fopen(pathDB.string().c_str(), "rb");
    CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
    if (filein.IsNull())
    {
        error("%s : Failed to open file %s", __func__, pathDB.string());
        return FileError;
    }

    // use file size to size memory buffer
    int fileSize = boost::filesystem::file_size(pathDB);
    int dataSize = fileSize - sizeof(uint256);
    // Don't try to resize to a negative number if file is small
    if (dataSize < 0)
        dataSize = 0;
    vector<unsigned char> vchData;
    vchData.resize(dataSize);
    uint256 hashIn;

    // read data and checksum from file
    try {
        filein.read((char *)&vchData[0], dataSize);
        filein >> hashIn;
    }
    catch (std::exception &e) {
        error("%s : Deserialize or I/O error - %s", __func__, e.what());
        return HashReadError;
    }
    filein.fclose();

    CDataStream ssObj(vchData, SER_DISK, CLIENT_VERSION);

    // verify stored checksum matches input data
    uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
    if (hashIn != hashTmp)
    {
        error("%s : Checksum mismatch, data corrupted", __func__);
        return IncorrectHash;
    }

    unsigned char pchMsgTmp[4];
    std::string strMagicMessageTmp;
    try {
        // de-serialize file header (coinbase payee cache file specific magic message) and ..
        ssObj >> strMagicMessageTmp;

        // ... verify the message matches predefined one
        if (strMagicMessage != strMagicMessageTmp)
        {
            error("%s : Invalid coinbase payee cache magic message", __func__);
            return IncorrectMagicMessage;
        }

        // de-serialize file header (network specific magic number) and ..
        ssObj >> FLATDATA(pchMsgTmp);

        // ... verify the network matches ours
        if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
        {
            error("%s : Invalid network magic number", __func__);
            return IncorrectMagicNumber;
        }

        // de-serialize data into CCoinbasePayee object
        ssObj >> objToLoad;
    }
    catch (std::exception &e) {
        objToLoad.Clear();
        error("%s : Deserialize or I/O error - %s", __func__, e.what());
        return IncorrectFormat;
    }

    objToLoad.CleanUp(); // clean out expired
    LogPrintf("Loaded info from coinbase-payee.dat  %dms\n", GetTimeMillis() - nStart);
    LogPrintf("  %s\n", objToLoad.ToString());

    return Ok;
}

void DumpCoinbasePayees()
{
    int64_t nStart = GetTimeMillis();

    CCoinbasePayeeDB mndb;
    CCoinbasePayee temp;

    LogPrintf("Verifying coinbase-payee.dat format...\n");
    CCoinbasePayeeDB::ReadResult readResult = mndb.Read(temp);
    // there was an error and it was not an error on file openning => do not proceed
    if (readResult == CCoinbasePayeeDB::FileError)
        LogPrintf("Missing payees cache file - coinbase-payee.dat, will try to recreate\n");
    else if (readResult != CCoinbasePayeeDB::Ok)
    {
        LogPrintf("Error reading coinbase-payee.dat: ");
        if(readResult == CCoinbasePayeeDB::IncorrectFormat)
            LogPrintf("magic is ok but data has invalid format, will try to recreate\n");
        else
        {
            LogPrintf("file format is unknown or invalid, please fix it manually\n");
            return;
        }
    }
    LogPrintf("Writting info to coinbase-payee.dat...\n");
    mndb.Write(coinbasePayee);

    LogPrintf("Coinbase payee dump finished  %dms\n", GetTimeMillis() - nStart);
}

void CCoinbasePayee::BuildIndex(bool bForced)
{
    if(mapPaidTime.size() > 0 && !bForced) {
        LogPrintf("CCoinbasePayee::BuildIndex - coinbase cache exists, skipping BuildIndex\n");
        return;
    } else if(bForced) {
        if(fDebug) LogPrintf("CCoinbasePayee::BuildIndex - Rebuilding coinbase cache\n");
        mapPaidTime.clear();
    }

    //scan last 30 days worth of blocks, run processBlockCoinbaseTX for each

    CBlockIndex* pindexPrev = chainActive.Tip();
    int count = 0;

    for (unsigned int i = 1; pindexPrev && pindexPrev->nHeight > 0; i++) {
        count++;
        if(count > 18000) return;

        CBlock block;
        if (ReadBlockFromDisk(block, pindexPrev)) {
            ProcessBlockCoinbaseTX(block.vtx[0], block.nTime);
        }

        if (pindexPrev->pprev == NULL) { assert(pindexPrev); break; }
        pindexPrev = pindexPrev->pprev;
    }

    return;
}

void CCoinbasePayee::ProcessBlockCoinbaseTX(CTransaction& txCoinbase, int64_t nTime)
{
    if (!txCoinbase.IsCoinBase()){
        LogPrintf("ERROR: CCoinbasePayee::ProcessBlockCoinbaseTX - tx is not coinbase\n");
        return;
    }

    BOOST_FOREACH(CTxOut out, txCoinbase.vout){
        uint256 h = GetScriptHash(out.scriptPubKey);
        LogPrintf("CCoinbasePayee::ProcessBlockCoinbaseTX - %s - %d\n", h.ToString(), nTime);
        if(mapPaidTime.count(h)){
            if(mapPaidTime[h] < nTime) {
                mapPaidTime[h] = nTime;
            }
        } else {
            mapPaidTime[h] = nTime;
        }
    }
}

int64_t CCoinbasePayee::GetLastPaid(CScript& pubkey)
{
    uint256 h = GetScriptHash(pubkey);

    if(mapPaidTime.count(h)){
        return mapPaidTime[h];
    }

    return 0;
}

void CCoinbasePayee::CleanUp()
{
    std::map<uint256, int64_t>::iterator it = mapPaidTime.begin();
    while(it != mapPaidTime.end())
    {
        //keep 30 days of history
        if((*it).second < GetAdjustedTime() - (60*60*24*30)) {
            mapPaidTime.erase(it++);
        } else {
            ++it;
        }
    }
}
<commit_msg>Disabled coinpayee cleanup<commit_after>// Copyright (c) 2014-2015 The Dash developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "coinbase-payee.h"
#include "util.h"
#include "addrman.h"
#include "masternode.h"
#include "darksend.h"
#include "masternodeman.h"
#include <boost/filesystem.hpp>

CCoinbasePayee coinbasePayee;

//
// CCoinbasePayeeDB
//

CCoinbasePayeeDB::CCoinbasePayeeDB()
{
    pathDB = GetDataDir() / "coinbase-payee.dat";
    strMagicMessage = "CoinbasePayeeDB";
}

bool CCoinbasePayeeDB::Write(const CCoinbasePayee& objToSave)
{
    int64_t nStart = GetTimeMillis();

    // serialize, checksum data up to that point, then append checksum
    CDataStream ssObj(SER_DISK, CLIENT_VERSION);
    ssObj << strMagicMessage; // coinbase payee cache file specific magic message
    ssObj << FLATDATA(Params().MessageStart()); // network specific magic number
    ssObj << objToSave;
    uint256 hash = Hash(ssObj.begin(), ssObj.end());
    ssObj << hash;

    // open output file, and associate with CAutoFile
    FILE *file = fopen(pathDB.string().c_str(), "wb");
    CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
    if (fileout.IsNull())
        return error("%s : Failed to open file %s", __func__, pathDB.string());

    // Write and commit header, data
    try {
        fileout << ssObj;
    }
    catch (std::exception &e) {
        return error("%s : Serialize or I/O error - %s", __func__, e.what());
    }
    fileout.fclose();

    LogPrintf("Written info to coinbase-payee.dat  %dms\n", GetTimeMillis() - nStart);

    return true;
}

CCoinbasePayeeDB::ReadResult CCoinbasePayeeDB::Read(CCoinbasePayee& objToLoad)
{

    int64_t nStart = GetTimeMillis();
    // open input file, and associate with CAutoFile
    FILE *file = fopen(pathDB.string().c_str(), "rb");
    CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
    if (filein.IsNull())
    {
        error("%s : Failed to open file %s", __func__, pathDB.string());
        return FileError;
    }

    // use file size to size memory buffer
    int fileSize = boost::filesystem::file_size(pathDB);
    int dataSize = fileSize - sizeof(uint256);
    // Don't try to resize to a negative number if file is small
    if (dataSize < 0)
        dataSize = 0;
    vector<unsigned char> vchData;
    vchData.resize(dataSize);
    uint256 hashIn;

    // read data and checksum from file
    try {
        filein.read((char *)&vchData[0], dataSize);
        filein >> hashIn;
    }
    catch (std::exception &e) {
        error("%s : Deserialize or I/O error - %s", __func__, e.what());
        return HashReadError;
    }
    filein.fclose();

    CDataStream ssObj(vchData, SER_DISK, CLIENT_VERSION);

    // verify stored checksum matches input data
    uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
    if (hashIn != hashTmp)
    {
        error("%s : Checksum mismatch, data corrupted", __func__);
        return IncorrectHash;
    }

    unsigned char pchMsgTmp[4];
    std::string strMagicMessageTmp;
    try {
        // de-serialize file header (coinbase payee cache file specific magic message) and ..
        ssObj >> strMagicMessageTmp;

        // ... verify the message matches predefined one
        if (strMagicMessage != strMagicMessageTmp)
        {
            error("%s : Invalid coinbase payee cache magic message", __func__);
            return IncorrectMagicMessage;
        }

        // de-serialize file header (network specific magic number) and ..
        ssObj >> FLATDATA(pchMsgTmp);

        // ... verify the network matches ours
        if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
        {
            error("%s : Invalid network magic number", __func__);
            return IncorrectMagicNumber;
        }

        // de-serialize data into CCoinbasePayee object
        ssObj >> objToLoad;
    }
    catch (std::exception &e) {
        objToLoad.Clear();
        error("%s : Deserialize or I/O error - %s", __func__, e.what());
        return IncorrectFormat;
    }

    objToLoad.CleanUp(); // clean out expired
    LogPrintf("Loaded info from coinbase-payee.dat  %dms\n", GetTimeMillis() - nStart);
    LogPrintf("  %s\n", objToLoad.ToString());

    return Ok;
}

void DumpCoinbasePayees()
{
    int64_t nStart = GetTimeMillis();

    CCoinbasePayeeDB mndb;
    CCoinbasePayee temp;

    LogPrintf("Verifying coinbase-payee.dat format...\n");
    CCoinbasePayeeDB::ReadResult readResult = mndb.Read(temp);
    // there was an error and it was not an error on file openning => do not proceed
    if (readResult == CCoinbasePayeeDB::FileError)
        LogPrintf("Missing payees cache file - coinbase-payee.dat, will try to recreate\n");
    else if (readResult != CCoinbasePayeeDB::Ok)
    {
        LogPrintf("Error reading coinbase-payee.dat: ");
        if(readResult == CCoinbasePayeeDB::IncorrectFormat)
            LogPrintf("magic is ok but data has invalid format, will try to recreate\n");
        else
        {
            LogPrintf("file format is unknown or invalid, please fix it manually\n");
            return;
        }
    }
    LogPrintf("Writting info to coinbase-payee.dat...\n");
    mndb.Write(coinbasePayee);

    LogPrintf("Coinbase payee dump finished  %dms\n", GetTimeMillis() - nStart);
}

void CCoinbasePayee::BuildIndex(bool bForced)
{
    if(mapPaidTime.size() > 0 && !bForced) {
        LogPrintf("CCoinbasePayee::BuildIndex - coinbase cache exists, skipping BuildIndex\n");
        return;
    } else if(bForced) {
        if(fDebug) LogPrintf("CCoinbasePayee::BuildIndex - Rebuilding coinbase cache\n");
        mapPaidTime.clear();
    }

    //scan last 30 days worth of blocks, run processBlockCoinbaseTX for each

    CBlockIndex* pindexPrev = chainActive.Tip();
    int count = 0;

    for (unsigned int i = 1; pindexPrev && pindexPrev->nHeight > 0; i++) {
        count++;
        if(count > 18000) return;

        CBlock block;
        if (ReadBlockFromDisk(block, pindexPrev)) {
            ProcessBlockCoinbaseTX(block.vtx[0], block.nTime);
        }

        if (pindexPrev->pprev == NULL) { assert(pindexPrev); break; }
        pindexPrev = pindexPrev->pprev;
    }

    return;
}

void CCoinbasePayee::ProcessBlockCoinbaseTX(CTransaction& txCoinbase, int64_t nTime)
{
    if (!txCoinbase.IsCoinBase()){
        LogPrintf("ERROR: CCoinbasePayee::ProcessBlockCoinbaseTX - tx is not coinbase\n");
        return;
    }

    BOOST_FOREACH(CTxOut out, txCoinbase.vout){
        uint256 h = GetScriptHash(out.scriptPubKey);
        LogPrintf("CCoinbasePayee::ProcessBlockCoinbaseTX - %s - %d\n", h.ToString(), nTime);
        if(mapPaidTime.count(h)){
            if(mapPaidTime[h] < nTime) {
                mapPaidTime[h] = nTime;
            } else {
                LogPrintf("CCoinbasePayee::ProcessBlockCoinbaseTX - not updated -- %s - %d\n", h.ToString(), nTime);
            }
        } else {
            mapPaidTime[h] = nTime;
        }
    }
}

int64_t CCoinbasePayee::GetLastPaid(CScript& pubkey)
{
    uint256 h = GetScriptHash(pubkey);

    if(mapPaidTime.count(h)){
        return mapPaidTime[h];
    }

    return 0;
}

void CCoinbasePayee::CleanUp()
{
    // std::map<uint256, int64_t>::iterator it = mapPaidTime.begin();
    // while(it != mapPaidTime.end())
    // {
    //     //keep 30 days of history
    //     if((*it).second < GetAdjustedTime() - (60*60*24*30)) {
    //         mapPaidTime.erase(it++);
    //     } else {
    //         ++it;
    //     }
    // }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/shell.h"
#include "ash/system/system_notifier.h"
#include "base/command_line.h"
#include "chrome/browser/chromeos/login/login_manager_test.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
#include "chrome/browser/notifications/login_state_notification_blocker_chromeos.h"
#include "content/public/test/test_utils.h"
#include "ui/message_center/message_center.h"

using namespace testing;

namespace {

const char* kTestUsers[] = {"test-user@gmail.com",
                            "test-user1@gmail.com"};

}  // anonymous namespace

class LoginStateNotificationBlockerChromeOSBrowserTest
    : public chromeos::LoginManagerTest,
      public message_center::NotificationBlocker::Observer {
 public:
  LoginStateNotificationBlockerChromeOSBrowserTest()
      : chromeos::LoginManagerTest(false),
        state_changed_count_(0) {}
  virtual ~LoginStateNotificationBlockerChromeOSBrowserTest() {}

  virtual void SetUpOnMainThread() override {
    chromeos::LoginState::Get()->set_always_logged_in(false);
    chromeos::LoginManagerTest::SetUpOnMainThread();
  }

  virtual void TearDownOnMainThread() override {
    if (blocker_)
      blocker_->RemoveObserver(this);
    blocker_.reset();
    chromeos::LoginManagerTest::TearDownOnMainThread();
  }

 protected:
  void CreateBlocker() {
    blocker_.reset(new LoginStateNotificationBlockerChromeOS(
        message_center::MessageCenter::Get()));
    blocker_->AddObserver(this);
  }

  // message_center::NotificationBlocker::Observer ovverrides:
  virtual void OnBlockingStateChanged(
      message_center::NotificationBlocker* blocker) override {
    state_changed_count_++;
  }

  int GetStateChangedCountAndReset() {
    int result = state_changed_count_;
    state_changed_count_ = 0;
    return result;
  }

  bool ShouldShowNotificationAsPopup(
      const message_center::NotifierId& notifier_id) {
    return blocker_->ShouldShowNotificationAsPopup(notifier_id);
  }

 private:
  int state_changed_count_;
  scoped_ptr<message_center::NotificationBlocker> blocker_;

  DISALLOW_COPY_AND_ASSIGN(LoginStateNotificationBlockerChromeOSBrowserTest);
};

IN_PROC_BROWSER_TEST_F(LoginStateNotificationBlockerChromeOSBrowserTest,
                       PRE_BaseTest) {
  RegisterUser(kTestUsers[0]);
  RegisterUser(kTestUsers[1]);
  chromeos::StartupUtils::MarkOobeCompleted();
}

IN_PROC_BROWSER_TEST_F(LoginStateNotificationBlockerChromeOSBrowserTest,
                       BaseTest) {
  CreateBlocker();
  message_center::NotifierId notifier_id(
      message_center::NotifierId::APPLICATION, "test-notifier");

  // Logged in as a normal user.
  EXPECT_CALL(login_utils(), DoBrowserLaunch(_, _)).Times(1);
  LoginUser(kTestUsers[0]);
  EXPECT_EQ(1, GetStateChangedCountAndReset());
  EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id));

  // Multi-login user switch.
  chromeos::UserAddingScreen::Get()->Start();
  content::RunAllPendingInMessageLoop();
  EXPECT_EQ(1, GetStateChangedCountAndReset());
  EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id));

  // Multi-login user switch off.
  chromeos::UserAddingScreen::Get()->Cancel();
  content::RunAllPendingInMessageLoop();
  EXPECT_EQ(1, GetStateChangedCountAndReset());
  EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id));
}

IN_PROC_BROWSER_TEST_F(LoginStateNotificationBlockerChromeOSBrowserTest,
                       PRE_AlwaysAllowedNotifier) {
  RegisterUser(kTestUsers[0]);
  RegisterUser(kTestUsers[1]);
  chromeos::StartupUtils::MarkOobeCompleted();
}

IN_PROC_BROWSER_TEST_F(LoginStateNotificationBlockerChromeOSBrowserTest,
                       AlwaysAllowedNotifier) {
  CreateBlocker();

  // NOTIFIER_DISPLAY is allowed to shown in the login screen.
  message_center::NotifierId notifier_id(
      message_center::NotifierId::SYSTEM_COMPONENT,
      ash::system_notifier::kNotifierDisplay);

  // Logged in as a normal user.
  EXPECT_CALL(login_utils(), DoBrowserLaunch(_, _)).Times(1);
  LoginUser(kTestUsers[0]);
  EXPECT_EQ(1, GetStateChangedCountAndReset());
  EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id));

  // Multi-login user switch.
  chromeos::UserAddingScreen::Get()->Start();
  content::RunAllPendingInMessageLoop();
  EXPECT_EQ(1, GetStateChangedCountAndReset());
  EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id));

  // Multi-login user switch off.
  chromeos::UserAddingScreen::Get()->Cancel();
  content::RunAllPendingInMessageLoop();
  EXPECT_EQ(1, GetStateChangedCountAndReset());
  EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id));
}
<commit_msg>Disable LoginStateNotificationBlockerChromeOSBrowserTest.BaseTest<commit_after>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/shell.h"
#include "ash/system/system_notifier.h"
#include "base/command_line.h"
#include "chrome/browser/chromeos/login/login_manager_test.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
#include "chrome/browser/notifications/login_state_notification_blocker_chromeos.h"
#include "content/public/test/test_utils.h"
#include "ui/message_center/message_center.h"

using namespace testing;

namespace {

const char* kTestUsers[] = {"test-user@gmail.com",
                            "test-user1@gmail.com"};

}  // anonymous namespace

class LoginStateNotificationBlockerChromeOSBrowserTest
    : public chromeos::LoginManagerTest,
      public message_center::NotificationBlocker::Observer {
 public:
  LoginStateNotificationBlockerChromeOSBrowserTest()
      : chromeos::LoginManagerTest(false),
        state_changed_count_(0) {}
  virtual ~LoginStateNotificationBlockerChromeOSBrowserTest() {}

  virtual void SetUpOnMainThread() override {
    chromeos::LoginState::Get()->set_always_logged_in(false);
    chromeos::LoginManagerTest::SetUpOnMainThread();
  }

  virtual void TearDownOnMainThread() override {
    if (blocker_)
      blocker_->RemoveObserver(this);
    blocker_.reset();
    chromeos::LoginManagerTest::TearDownOnMainThread();
  }

 protected:
  void CreateBlocker() {
    blocker_.reset(new LoginStateNotificationBlockerChromeOS(
        message_center::MessageCenter::Get()));
    blocker_->AddObserver(this);
  }

  // message_center::NotificationBlocker::Observer ovverrides:
  virtual void OnBlockingStateChanged(
      message_center::NotificationBlocker* blocker) override {
    state_changed_count_++;
  }

  int GetStateChangedCountAndReset() {
    int result = state_changed_count_;
    state_changed_count_ = 0;
    return result;
  }

  bool ShouldShowNotificationAsPopup(
      const message_center::NotifierId& notifier_id) {
    return blocker_->ShouldShowNotificationAsPopup(notifier_id);
  }

 private:
  int state_changed_count_;
  scoped_ptr<message_center::NotificationBlocker> blocker_;

  DISALLOW_COPY_AND_ASSIGN(LoginStateNotificationBlockerChromeOSBrowserTest);
};

IN_PROC_BROWSER_TEST_F(LoginStateNotificationBlockerChromeOSBrowserTest,
                       PRE_BaseTest) {
  RegisterUser(kTestUsers[0]);
  RegisterUser(kTestUsers[1]);
  chromeos::StartupUtils::MarkOobeCompleted();
}

 // Disabled due to flakiness. See: http://crbug.com/421325.
IN_PROC_BROWSER_TEST_F(LoginStateNotificationBlockerChromeOSBrowserTest,
                       DISABLED_BaseTest) {
  CreateBlocker();
  message_center::NotifierId notifier_id(
      message_center::NotifierId::APPLICATION, "test-notifier");

  // Logged in as a normal user.
  EXPECT_CALL(login_utils(), DoBrowserLaunch(_, _)).Times(1);
  LoginUser(kTestUsers[0]);
  EXPECT_EQ(1, GetStateChangedCountAndReset());
  EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id));

  // Multi-login user switch.
  chromeos::UserAddingScreen::Get()->Start();
  content::RunAllPendingInMessageLoop();
  EXPECT_EQ(1, GetStateChangedCountAndReset());
  EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id));

  // Multi-login user switch off.
  chromeos::UserAddingScreen::Get()->Cancel();
  content::RunAllPendingInMessageLoop();
  EXPECT_EQ(1, GetStateChangedCountAndReset());
  EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id));
}

IN_PROC_BROWSER_TEST_F(LoginStateNotificationBlockerChromeOSBrowserTest,
                       PRE_AlwaysAllowedNotifier) {
  RegisterUser(kTestUsers[0]);
  RegisterUser(kTestUsers[1]);
  chromeos::StartupUtils::MarkOobeCompleted();
}

IN_PROC_BROWSER_TEST_F(LoginStateNotificationBlockerChromeOSBrowserTest,
                       AlwaysAllowedNotifier) {
  CreateBlocker();

  // NOTIFIER_DISPLAY is allowed to shown in the login screen.
  message_center::NotifierId notifier_id(
      message_center::NotifierId::SYSTEM_COMPONENT,
      ash::system_notifier::kNotifierDisplay);

  // Logged in as a normal user.
  EXPECT_CALL(login_utils(), DoBrowserLaunch(_, _)).Times(1);
  LoginUser(kTestUsers[0]);
  EXPECT_EQ(1, GetStateChangedCountAndReset());
  EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id));

  // Multi-login user switch.
  chromeos::UserAddingScreen::Get()->Start();
  content::RunAllPendingInMessageLoop();
  EXPECT_EQ(1, GetStateChangedCountAndReset());
  EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id));

  // Multi-login user switch off.
  chromeos::UserAddingScreen::Get()->Cancel();
  content::RunAllPendingInMessageLoop();
  EXPECT_EQ(1, GetStateChangedCountAndReset());
  EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id));
}
<|endoftext|>


<commit_before>#include "commonFunctionL.h"
#include "testDataL.h"
#include "init.h"
using namespace ODBC;
#include "ctosqlconv.h"

void callSubCtosql(int n, CDescRec* tmpDesc){

    string s = TESTDATA_MAPL[n].cValue;
    initDesc(tmpDesc, TESTDATA_MAPL[n]);
    ICUConverter* iconv;
    char* tmpbuf = NULL;

    switch(TESTDATA_MAPL[n].CDataType){
        case SQL_C_TINYINT:
        case SQL_C_STINYINT:{
            char testSrc = stringToNum<int>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;
        }
        case SQL_C_BIT:
        case SQL_C_UTINYINT:{
            unsigned char testSrc = stringToNum<int>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        case SQL_C_SHORT:
        case SQL_C_SSHORT:{
            short testSrc = stringToNum<short>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;
        }
        case SQL_C_USHORT:{
            unsigned short testSrc = stringToNum<unsigned short>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        case SQL_C_SLONG:
        case SQL_C_LONG:{
            long testSrc = stringToNum<long>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        case SQL_C_ULONG:{
            unsigned  long testSrc = stringToNum<unsigned long>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;
        }
        case SQL_C_SBIGINT:{
            long long  testSrc = stringToNum<long long>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        case SQL_C_UBIGINT:{
            unsigned long long  testSrc = stringToNum<unsigned long long >(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        case SQL_C_FLOAT:{
            float testSrc = stringToNum<float>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        case SQL_C_DOUBLE:{
            double testSrc = stringToNum<double>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        default:
        break;
    }

}

void commonSwitchctosql(int m_ODBCDataType, SQLPOINTER testP, int n){

    switch(m_ODBCDataType){

        case SQL_BIT:{
            char mtarget = *(char *)testP;
            char sqldata = stringToNum<int>(TESTDATA_MAPL[n].sqlValue);
            EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
            delete((char *)testP);
            break;
        }
        case SQL_TINYINT:{
            char mtarget = *(char *)testP;
            char sqldata = stringToNum<int>(TESTDATA_MAPL[n].sqlValue);
            EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
            delete((char *)testP);
            break;

                         }
        case SQL_SMALLINT:{
            short   mtarget = *(short *)testP;
            short  sqldata = stringToNum<short>(TESTDATA_MAPL[n].sqlValue);
            EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
            delete((short *)testP);
            break;

        }
        case SQL_INTEGER:{

            int mtarget = *(int *)testP;
            int sqldata = stringToNum<int>(TESTDATA_MAPL[n].sqlValue);
            EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
            delete((int *)testP);
            break;
        }
        case SQL_BIGINT:{

            long long  mtarget = *(long long  *)testP;
            long long  sqldata = stringToNum<long long>(TESTDATA_MAPL[n].sqlValue);
            EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
            delete((long long *)testP);
            break;
        }
        case SQL_REAL:
            break;//TODO
        case SQL_DOUBLE:{

            double mtarget = *(double *)testP;
            double sqldata = stringToNum<double>(TESTDATA_MAPL[n].sqlValue);
            EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
            delete((double *)testP);
            break;
        }
        case SQL_CHAR:
        case SQL_WCHAR:
        case SQL_VARCHAR:
        case SQL_WVARCHAR:
        case SQL_LONGVARCHAR:
             break;//TODO
        case SQL_NUMERIC:
             SQL_NUMERIC_STRUCT testSrc;
             break;
        case SQL_DATE:
             break;
        case SQL_TIME:
             break;
        case SQL_TIMESTAMP:
             break;
        case SQL_FLOAT: // no need
             break;
        default:
            EXPECT_TRUE(false) << "the DataType is :" << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName;
            break;
    }
}

<commit_msg>LZ:add unsigned support<commit_after>#include "commonFunctionL.h"
#include "testDataL.h"
#include "init.h"
using namespace ODBC;
#include "ctosqlconv.h"

void callSubCtosql(int n, CDescRec* tmpDesc){

    string s = TESTDATA_MAPL[n].cValue;
    initDesc(tmpDesc, TESTDATA_MAPL[n]);
    ICUConverter* iconv;
    char* tmpbuf = NULL;

    switch(TESTDATA_MAPL[n].CDataType){
        case SQL_C_TINYINT:
        case SQL_C_STINYINT:{
            char testSrc = stringToNum<int>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;
        }
        case SQL_C_BIT:
        case SQL_C_UTINYINT:{
            unsigned char testSrc = stringToNum<int>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        case SQL_C_SHORT:
        case SQL_C_SSHORT:{
            short testSrc = stringToNum<short>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;
        }
        case SQL_C_USHORT:{
            unsigned short testSrc = stringToNum<unsigned short>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        case SQL_C_SLONG:
        case SQL_C_LONG:{
            long testSrc = stringToNum<long>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        case SQL_C_ULONG:{
            unsigned  long testSrc = stringToNum<unsigned long>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;
        }
        case SQL_C_SBIGINT:{
            long long  testSrc = stringToNum<long long>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        case SQL_C_UBIGINT:{
            unsigned long long  testSrc = stringToNum<unsigned long long >(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        case SQL_C_FLOAT:{
            float testSrc = stringToNum<float>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        case SQL_C_DOUBLE:{
            double testSrc = stringToNum<double>(s);
            SQLPOINTER testP = malloc(sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            memset(testP, 0,sizeof(char) * TESTDATA_MAPL[n].m_SQLMaxLength);
            SQLLEN size;
            ConvertCToSQL(3,TESTDATA_MAPL[n].CDataType, &testSrc, sizeof(testSrc), testP, tmpDesc, false, iconv);
            commonSwitchctosql(TESTDATA_MAPL[n].m_ODBCDataType, testP, n);
            break;

        }
        default:
        break;
    }

}

void commonSwitchctosql(int m_ODBCDataType, SQLPOINTER testP, int n){

    switch(m_ODBCDataType){

        case SQL_BIT:{
            char mtarget = *(char *)testP;
            char sqldata = stringToNum<int>(TESTDATA_MAPL[n].sqlValue);
            EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
            delete((char *)testP);
            break;
        }
        case SQL_TINYINT:{

                             if(TESTDATA_MAPL[n].m_DescUnsigned)
                             {
                                 unsigned char mtarget = *(unsigned char *)testP;
                                 unsigned char sqldata = stringToNum<int>(TESTDATA_MAPL[n].sqlValue);
                                 EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
                                 delete((unsigned char *)testP);

                             }
                             else
                             {

                                 char mtarget = *(char *)testP;
                                 char sqldata = stringToNum<int>(TESTDATA_MAPL[n].sqlValue);
                                 EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
                                 delete((char *)testP);

                             }
                             break;

                         }
        case SQL_SMALLINT:{

                              if(TESTDATA_MAPL[n].m_DescUnsigned)
                              {

                                  unsigned short   mtarget = *(unsigned short *)testP;
                                  unsigned short   sqldata = stringToNum<unsigned short>(TESTDATA_MAPL[n].sqlValue);
                                  EXPECT_FLOAT_EQ((unsigned short)sqldata, (unsigned short)mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;

                                  delete((unsigned short *)testP);
                              }
                              else
                              {

                                  short   mtarget = *(short *)testP;
                                  short   sqldata = stringToNum<short>(TESTDATA_MAPL[n].sqlValue);
                                  EXPECT_FLOAT_EQ((short)sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;

                                  delete((short *)testP);
                              }
                              break;

                          }
        case SQL_INTEGER:{

                             if(TESTDATA_MAPL[n].m_DescUnsigned)
                             {

                                 unsigned int mtarget = *(unsigned int *)testP;
                                 unsigned int sqldata = stringToNum<unsigned int>(TESTDATA_MAPL[n].sqlValue);
                                 EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
                                 delete((unsigned int *)testP);

                             }
                             else{

                                 int mtarget = *(int *)testP;
                                 int sqldata = stringToNum<int>(TESTDATA_MAPL[n].sqlValue);
                                 EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
                                 delete((int *)testP);
                             }
                             break;
        }
        case SQL_BIGINT:{

                            if(TESTDATA_MAPL[n].m_DescUnsigned)
                            {
                                unsigned long long  mtarget = *(unsigned long long  *)testP;
                                unsigned long long  sqldata = stringToNum<unsigned long long>(TESTDATA_MAPL[n].sqlValue);
                                EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
                                delete((unsigned long long *)testP);

                            }
                            else
                            {

                                long long  mtarget = *(long long  *)testP;
                                long long  sqldata = stringToNum<long long>(TESTDATA_MAPL[n].sqlValue);
                                EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
                                delete((long long *)testP);
                            }
            break;
        }
        case SQL_REAL:
            break;//TODO
        case SQL_DOUBLE:{

            double mtarget = *(double *)testP;
            double sqldata = stringToNum<double>(TESTDATA_MAPL[n].sqlValue);
            EXPECT_FLOAT_EQ(sqldata, mtarget) << "Data type is: " <<TESTDATA_MAPL[n].CTypeName  << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName ;
            delete((double *)testP);
            break;
        }
        case SQL_CHAR:
        case SQL_WCHAR:
        case SQL_VARCHAR:
        case SQL_WVARCHAR:
        case SQL_LONGVARCHAR:
             break;//TODO
        case SQL_NUMERIC:
             SQL_NUMERIC_STRUCT testSrc;
             break;
        case SQL_DATE:
             break;
        case SQL_TIME:
             break;
        case SQL_TIMESTAMP:
             break;
        case SQL_FLOAT: // no need
             break;
        default:
            EXPECT_TRUE(false) << "the DataType is :" << "targettype is: " <<TESTDATA_MAPL[n].SQLTypeName;
            break;
    }
}

<|endoftext|>