<commit_before>// Copyright (c) 2015-2016 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "source/spirv_target_env.h"

#include <cstring>
#include <map>
#include <string>

#include "source/spirv_constant.h"
#include "spirv-tools/libspirv.h"

const char* spvTargetEnvDescription(spv_target_env env) {
  switch (env) {
    case SPV_ENV_UNIVERSAL_1_0:
      return "SPIR-V 1.0";
    case SPV_ENV_VULKAN_1_0:
      return "SPIR-V 1.0 (under Vulkan 1.0 semantics)";
    case SPV_ENV_UNIVERSAL_1_1:
      return "SPIR-V 1.1";
    case SPV_ENV_OPENCL_1_2:
      return "SPIR-V 1.0 (under OpenCL 1.2 Full Profile semantics)";
    case SPV_ENV_OPENCL_EMBEDDED_1_2:
      return "SPIR-V 1.0 (under OpenCL 1.2 Embedded Profile semantics)";
    case SPV_ENV_OPENCL_2_0:
      return "SPIR-V 1.0 (under OpenCL 2.0 Full Profile semantics)";
    case SPV_ENV_OPENCL_EMBEDDED_2_0:
      return "SPIR-V 1.0 (under OpenCL 2.0 Embedded Profile semantics)";
    case SPV_ENV_OPENCL_2_1:
      return "SPIR-V 1.0 (under OpenCL 2.1 Full Profile semantics)";
    case SPV_ENV_OPENCL_EMBEDDED_2_1:
      return "SPIR-V 1.0 (under OpenCL 2.1 Embedded Profile semantics)";
    case SPV_ENV_OPENCL_2_2:
      return "SPIR-V 1.2 (under OpenCL 2.2 Full Profile semantics)";
    case SPV_ENV_OPENCL_EMBEDDED_2_2:
      return "SPIR-V 1.2 (under OpenCL 2.2 Embedded Profile semantics)";
    case SPV_ENV_OPENGL_4_0:
      return "SPIR-V 1.0 (under OpenGL 4.0 semantics)";
    case SPV_ENV_OPENGL_4_1:
      return "SPIR-V 1.0 (under OpenGL 4.1 semantics)";
    case SPV_ENV_OPENGL_4_2:
      return "SPIR-V 1.0 (under OpenGL 4.2 semantics)";
    case SPV_ENV_OPENGL_4_3:
      return "SPIR-V 1.0 (under OpenGL 4.3 semantics)";
    case SPV_ENV_OPENGL_4_5:
      return "SPIR-V 1.0 (under OpenGL 4.5 semantics)";
    case SPV_ENV_UNIVERSAL_1_2:
      return "SPIR-V 1.2";
    case SPV_ENV_UNIVERSAL_1_3:
      return "SPIR-V 1.3";
    case SPV_ENV_VULKAN_1_1:
      return "SPIR-V 1.3 (under Vulkan 1.1 semantics)";
    case SPV_ENV_WEBGPU_0:
      return "SPIR-V 1.3 (under WIP WebGPU semantics)";
    case SPV_ENV_UNIVERSAL_1_4:
      return "SPIR-V 1.4";
    case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
      return "SPIR-V 1.4 (under Vulkan 1.1 semantics)";
  }
  return "";
}

uint32_t spvVersionForTargetEnv(spv_target_env env) {
  switch (env) {
    case SPV_ENV_UNIVERSAL_1_0:
    case SPV_ENV_VULKAN_1_0:
    case SPV_ENV_OPENCL_1_2:
    case SPV_ENV_OPENCL_EMBEDDED_1_2:
    case SPV_ENV_OPENCL_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_0:
    case SPV_ENV_OPENCL_2_1:
    case SPV_ENV_OPENCL_EMBEDDED_2_1:
    case SPV_ENV_OPENGL_4_0:
    case SPV_ENV_OPENGL_4_1:
    case SPV_ENV_OPENGL_4_2:
    case SPV_ENV_OPENGL_4_3:
    case SPV_ENV_OPENGL_4_5:
      return SPV_SPIRV_VERSION_WORD(1, 0);
    case SPV_ENV_UNIVERSAL_1_1:
      return SPV_SPIRV_VERSION_WORD(1, 1);
    case SPV_ENV_UNIVERSAL_1_2:
    case SPV_ENV_OPENCL_2_2:
    case SPV_ENV_OPENCL_EMBEDDED_2_2:
      return SPV_SPIRV_VERSION_WORD(1, 2);
    case SPV_ENV_UNIVERSAL_1_3:
    case SPV_ENV_VULKAN_1_1:
    case SPV_ENV_WEBGPU_0:
      return SPV_SPIRV_VERSION_WORD(1, 3);
    case SPV_ENV_UNIVERSAL_1_4:
    case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
      return SPV_SPIRV_VERSION_WORD(1, 4);
  }
  return SPV_SPIRV_VERSION_WORD(0, 0);
}

static const std::map<std::string, spv_target_env> spvTargetEnvNameMap = {
    {"vulkan1.1spv1.4", SPV_ENV_VULKAN_1_1_SPIRV_1_4},
    {"vulkan1.0", SPV_ENV_VULKAN_1_0},
    {"vulkan1.1", SPV_ENV_VULKAN_1_1},
    {"spv1.0", SPV_ENV_UNIVERSAL_1_0},
    {"spv1.1", SPV_ENV_UNIVERSAL_1_1},
    {"spv1.2", SPV_ENV_UNIVERSAL_1_2},
    {"spv1.3", SPV_ENV_UNIVERSAL_1_3},
    {"spv1.4", SPV_ENV_UNIVERSAL_1_4},
    {"opencl1.2embedded", SPV_ENV_OPENCL_EMBEDDED_1_2},
    {"opencl1.2", SPV_ENV_OPENCL_1_2},
    {"opencl2.0embedded", SPV_ENV_OPENCL_EMBEDDED_2_0},
    {"opencl2.0", SPV_ENV_OPENCL_2_0},
    {"opencl2.1embedded", SPV_ENV_OPENCL_EMBEDDED_2_1},
    {"opencl2.1", SPV_ENV_OPENCL_2_1},
    {"opencl2.2embedded", SPV_ENV_OPENCL_EMBEDDED_2_2},
    {"opencl2.2", SPV_ENV_OPENCL_2_2},
    {"opengl4.0", SPV_ENV_OPENGL_4_0},
    {"opengl4.1", SPV_ENV_OPENGL_4_1},
    {"opengl4.2", SPV_ENV_OPENGL_4_2},
    {"opengl4.3", SPV_ENV_OPENGL_4_3},
    {"opengl4.5", SPV_ENV_OPENGL_4_5},
    {"webgpu0", SPV_ENV_WEBGPU_0},
};

bool spvParseTargetEnv(const char* s, spv_target_env* env) {
  std::string envstr;
  if (s != nullptr) {
    envstr = s;
  }
  if (spvTargetEnvNameMap.count(envstr) != 0) {
    if (env) {
      *env = spvTargetEnvNameMap.at(envstr);
    }
    return true;
  }
  if (env) *env = SPV_ENV_UNIVERSAL_1_0;
  return false;
}

bool spvIsVulkanEnv(spv_target_env env) {
  switch (env) {
    case SPV_ENV_UNIVERSAL_1_0:
    case SPV_ENV_OPENCL_1_2:
    case SPV_ENV_OPENCL_EMBEDDED_1_2:
    case SPV_ENV_OPENCL_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_0:
    case SPV_ENV_OPENCL_2_1:
    case SPV_ENV_OPENCL_EMBEDDED_2_1:
    case SPV_ENV_OPENGL_4_0:
    case SPV_ENV_OPENGL_4_1:
    case SPV_ENV_OPENGL_4_2:
    case SPV_ENV_OPENGL_4_3:
    case SPV_ENV_OPENGL_4_5:
    case SPV_ENV_UNIVERSAL_1_1:
    case SPV_ENV_UNIVERSAL_1_2:
    case SPV_ENV_OPENCL_2_2:
    case SPV_ENV_OPENCL_EMBEDDED_2_2:
    case SPV_ENV_UNIVERSAL_1_3:
    case SPV_ENV_WEBGPU_0:
    case SPV_ENV_UNIVERSAL_1_4:
      return false;
    case SPV_ENV_VULKAN_1_0:
    case SPV_ENV_VULKAN_1_1:
    case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
      return true;
  }
  return false;
}

bool spvIsOpenCLEnv(spv_target_env env) {
  switch (env) {
    case SPV_ENV_UNIVERSAL_1_0:
    case SPV_ENV_VULKAN_1_0:
    case SPV_ENV_UNIVERSAL_1_1:
    case SPV_ENV_OPENGL_4_0:
    case SPV_ENV_OPENGL_4_1:
    case SPV_ENV_OPENGL_4_2:
    case SPV_ENV_OPENGL_4_3:
    case SPV_ENV_OPENGL_4_5:
    case SPV_ENV_UNIVERSAL_1_2:
    case SPV_ENV_UNIVERSAL_1_3:
    case SPV_ENV_VULKAN_1_1:
    case SPV_ENV_WEBGPU_0:
    case SPV_ENV_UNIVERSAL_1_4:
    case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
      return false;
    case SPV_ENV_OPENCL_1_2:
    case SPV_ENV_OPENCL_EMBEDDED_1_2:
    case SPV_ENV_OPENCL_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_1:
    case SPV_ENV_OPENCL_EMBEDDED_2_2:
    case SPV_ENV_OPENCL_2_1:
    case SPV_ENV_OPENCL_2_2:
      return true;
  }
  return false;
}

bool spvIsWebGPUEnv(spv_target_env env) {
  switch (env) {
    case SPV_ENV_UNIVERSAL_1_0:
    case SPV_ENV_VULKAN_1_0:
    case SPV_ENV_UNIVERSAL_1_1:
    case SPV_ENV_OPENGL_4_0:
    case SPV_ENV_OPENGL_4_1:
    case SPV_ENV_OPENGL_4_2:
    case SPV_ENV_OPENGL_4_3:
    case SPV_ENV_OPENGL_4_5:
    case SPV_ENV_UNIVERSAL_1_2:
    case SPV_ENV_UNIVERSAL_1_3:
    case SPV_ENV_VULKAN_1_1:
    case SPV_ENV_OPENCL_1_2:
    case SPV_ENV_OPENCL_EMBEDDED_1_2:
    case SPV_ENV_OPENCL_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_1:
    case SPV_ENV_OPENCL_EMBEDDED_2_2:
    case SPV_ENV_OPENCL_2_1:
    case SPV_ENV_OPENCL_2_2:
    case SPV_ENV_UNIVERSAL_1_4:
    case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
      return false;
    case SPV_ENV_WEBGPU_0:
      return true;
  }
  return false;
}

bool spvIsVulkanOrWebGPUEnv(spv_target_env env) {
  return spvIsVulkanEnv(env) || spvIsWebGPUEnv(env);
}

std::string spvLogStringForEnv(spv_target_env env) {
  switch (env) {
    case SPV_ENV_OPENCL_1_2:
    case SPV_ENV_OPENCL_2_0:
    case SPV_ENV_OPENCL_2_1:
    case SPV_ENV_OPENCL_2_2:
    case SPV_ENV_OPENCL_EMBEDDED_1_2:
    case SPV_ENV_OPENCL_EMBEDDED_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_1:
    case SPV_ENV_OPENCL_EMBEDDED_2_2: {
      return "OpenCL";
    }
    case SPV_ENV_OPENGL_4_0:
    case SPV_ENV_OPENGL_4_1:
    case SPV_ENV_OPENGL_4_2:
    case SPV_ENV_OPENGL_4_3:
    case SPV_ENV_OPENGL_4_5: {
      return "OpenGL";
    }
    case SPV_ENV_VULKAN_1_0:
    case SPV_ENV_VULKAN_1_1:
    case SPV_ENV_VULKAN_1_1_SPIRV_1_4: {
      return "Vulkan";
    }
    case SPV_ENV_WEBGPU_0: {
      return "WebGPU";
    }
    case SPV_ENV_UNIVERSAL_1_0:
    case SPV_ENV_UNIVERSAL_1_1:
    case SPV_ENV_UNIVERSAL_1_2:
    case SPV_ENV_UNIVERSAL_1_3:
    case SPV_ENV_UNIVERSAL_1_4: {
      return "Universal";
    }
  }
  return "Unknown";
}

std::string spvTargetEnvList(const int pad, const int wrap) {
  std::string ret;
  size_t max_line_len = wrap - pad;  // The first line isn't padded
  std::string line;
  std::string sep = "";

  for (auto& env_name : spvTargetEnvNameMap) {
    std::string word = sep + env_name.first;
    if (line.length() + word.length() > max_line_len) {
      // Adding one word wouldn't fit, commit the line in progress and
      // start a new one.
      ret += line + "\n";
      line.assign(pad, ' ');
      // The first line is done. The max length now comprises the
      // padding.
      max_line_len = wrap;
    }
    line += word;
    sep = "|";
  }

  ret += line;

  return ret;
}
<commit_msg>Replace global static map with an array of pairs (#2691)<commit_after>// Copyright (c) 2015-2016 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "source/spirv_target_env.h"

#include <cstring>
#include <string>

#include "source/spirv_constant.h"
#include "spirv-tools/libspirv.h"

const char* spvTargetEnvDescription(spv_target_env env) {
  switch (env) {
    case SPV_ENV_UNIVERSAL_1_0:
      return "SPIR-V 1.0";
    case SPV_ENV_VULKAN_1_0:
      return "SPIR-V 1.0 (under Vulkan 1.0 semantics)";
    case SPV_ENV_UNIVERSAL_1_1:
      return "SPIR-V 1.1";
    case SPV_ENV_OPENCL_1_2:
      return "SPIR-V 1.0 (under OpenCL 1.2 Full Profile semantics)";
    case SPV_ENV_OPENCL_EMBEDDED_1_2:
      return "SPIR-V 1.0 (under OpenCL 1.2 Embedded Profile semantics)";
    case SPV_ENV_OPENCL_2_0:
      return "SPIR-V 1.0 (under OpenCL 2.0 Full Profile semantics)";
    case SPV_ENV_OPENCL_EMBEDDED_2_0:
      return "SPIR-V 1.0 (under OpenCL 2.0 Embedded Profile semantics)";
    case SPV_ENV_OPENCL_2_1:
      return "SPIR-V 1.0 (under OpenCL 2.1 Full Profile semantics)";
    case SPV_ENV_OPENCL_EMBEDDED_2_1:
      return "SPIR-V 1.0 (under OpenCL 2.1 Embedded Profile semantics)";
    case SPV_ENV_OPENCL_2_2:
      return "SPIR-V 1.2 (under OpenCL 2.2 Full Profile semantics)";
    case SPV_ENV_OPENCL_EMBEDDED_2_2:
      return "SPIR-V 1.2 (under OpenCL 2.2 Embedded Profile semantics)";
    case SPV_ENV_OPENGL_4_0:
      return "SPIR-V 1.0 (under OpenGL 4.0 semantics)";
    case SPV_ENV_OPENGL_4_1:
      return "SPIR-V 1.0 (under OpenGL 4.1 semantics)";
    case SPV_ENV_OPENGL_4_2:
      return "SPIR-V 1.0 (under OpenGL 4.2 semantics)";
    case SPV_ENV_OPENGL_4_3:
      return "SPIR-V 1.0 (under OpenGL 4.3 semantics)";
    case SPV_ENV_OPENGL_4_5:
      return "SPIR-V 1.0 (under OpenGL 4.5 semantics)";
    case SPV_ENV_UNIVERSAL_1_2:
      return "SPIR-V 1.2";
    case SPV_ENV_UNIVERSAL_1_3:
      return "SPIR-V 1.3";
    case SPV_ENV_VULKAN_1_1:
      return "SPIR-V 1.3 (under Vulkan 1.1 semantics)";
    case SPV_ENV_WEBGPU_0:
      return "SPIR-V 1.3 (under WIP WebGPU semantics)";
    case SPV_ENV_UNIVERSAL_1_4:
      return "SPIR-V 1.4";
    case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
      return "SPIR-V 1.4 (under Vulkan 1.1 semantics)";
  }
  return "";
}

uint32_t spvVersionForTargetEnv(spv_target_env env) {
  switch (env) {
    case SPV_ENV_UNIVERSAL_1_0:
    case SPV_ENV_VULKAN_1_0:
    case SPV_ENV_OPENCL_1_2:
    case SPV_ENV_OPENCL_EMBEDDED_1_2:
    case SPV_ENV_OPENCL_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_0:
    case SPV_ENV_OPENCL_2_1:
    case SPV_ENV_OPENCL_EMBEDDED_2_1:
    case SPV_ENV_OPENGL_4_0:
    case SPV_ENV_OPENGL_4_1:
    case SPV_ENV_OPENGL_4_2:
    case SPV_ENV_OPENGL_4_3:
    case SPV_ENV_OPENGL_4_5:
      return SPV_SPIRV_VERSION_WORD(1, 0);
    case SPV_ENV_UNIVERSAL_1_1:
      return SPV_SPIRV_VERSION_WORD(1, 1);
    case SPV_ENV_UNIVERSAL_1_2:
    case SPV_ENV_OPENCL_2_2:
    case SPV_ENV_OPENCL_EMBEDDED_2_2:
      return SPV_SPIRV_VERSION_WORD(1, 2);
    case SPV_ENV_UNIVERSAL_1_3:
    case SPV_ENV_VULKAN_1_1:
    case SPV_ENV_WEBGPU_0:
      return SPV_SPIRV_VERSION_WORD(1, 3);
    case SPV_ENV_UNIVERSAL_1_4:
    case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
      return SPV_SPIRV_VERSION_WORD(1, 4);
  }
  return SPV_SPIRV_VERSION_WORD(0, 0);
}

static const std::pair<const char*, spv_target_env> spvTargetEnvNameMap[] = {
    {"vulkan1.1spv1.4", SPV_ENV_VULKAN_1_1_SPIRV_1_4},
    {"vulkan1.0", SPV_ENV_VULKAN_1_0},
    {"vulkan1.1", SPV_ENV_VULKAN_1_1},
    {"spv1.0", SPV_ENV_UNIVERSAL_1_0},
    {"spv1.1", SPV_ENV_UNIVERSAL_1_1},
    {"spv1.2", SPV_ENV_UNIVERSAL_1_2},
    {"spv1.3", SPV_ENV_UNIVERSAL_1_3},
    {"spv1.4", SPV_ENV_UNIVERSAL_1_4},
    {"opencl1.2embedded", SPV_ENV_OPENCL_EMBEDDED_1_2},
    {"opencl1.2", SPV_ENV_OPENCL_1_2},
    {"opencl2.0embedded", SPV_ENV_OPENCL_EMBEDDED_2_0},
    {"opencl2.0", SPV_ENV_OPENCL_2_0},
    {"opencl2.1embedded", SPV_ENV_OPENCL_EMBEDDED_2_1},
    {"opencl2.1", SPV_ENV_OPENCL_2_1},
    {"opencl2.2embedded", SPV_ENV_OPENCL_EMBEDDED_2_2},
    {"opencl2.2", SPV_ENV_OPENCL_2_2},
    {"opengl4.0", SPV_ENV_OPENGL_4_0},
    {"opengl4.1", SPV_ENV_OPENGL_4_1},
    {"opengl4.2", SPV_ENV_OPENGL_4_2},
    {"opengl4.3", SPV_ENV_OPENGL_4_3},
    {"opengl4.5", SPV_ENV_OPENGL_4_5},
    {"webgpu0", SPV_ENV_WEBGPU_0},
};

bool spvParseTargetEnv(const char* s, spv_target_env* env) {
  auto match = [s](const char* b) {
    return s && (0 == strncmp(s, b, strlen(b)));
  };
  for (auto& name_env : spvTargetEnvNameMap) {
    if (match(name_env.first)) {
      if (env) {
        *env = name_env.second;
      }
      return true;
    }
  }
  if (env) *env = SPV_ENV_UNIVERSAL_1_0;
  return false;
}

bool spvIsVulkanEnv(spv_target_env env) {
  switch (env) {
    case SPV_ENV_UNIVERSAL_1_0:
    case SPV_ENV_OPENCL_1_2:
    case SPV_ENV_OPENCL_EMBEDDED_1_2:
    case SPV_ENV_OPENCL_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_0:
    case SPV_ENV_OPENCL_2_1:
    case SPV_ENV_OPENCL_EMBEDDED_2_1:
    case SPV_ENV_OPENGL_4_0:
    case SPV_ENV_OPENGL_4_1:
    case SPV_ENV_OPENGL_4_2:
    case SPV_ENV_OPENGL_4_3:
    case SPV_ENV_OPENGL_4_5:
    case SPV_ENV_UNIVERSAL_1_1:
    case SPV_ENV_UNIVERSAL_1_2:
    case SPV_ENV_OPENCL_2_2:
    case SPV_ENV_OPENCL_EMBEDDED_2_2:
    case SPV_ENV_UNIVERSAL_1_3:
    case SPV_ENV_WEBGPU_0:
    case SPV_ENV_UNIVERSAL_1_4:
      return false;
    case SPV_ENV_VULKAN_1_0:
    case SPV_ENV_VULKAN_1_1:
    case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
      return true;
  }
  return false;
}

bool spvIsOpenCLEnv(spv_target_env env) {
  switch (env) {
    case SPV_ENV_UNIVERSAL_1_0:
    case SPV_ENV_VULKAN_1_0:
    case SPV_ENV_UNIVERSAL_1_1:
    case SPV_ENV_OPENGL_4_0:
    case SPV_ENV_OPENGL_4_1:
    case SPV_ENV_OPENGL_4_2:
    case SPV_ENV_OPENGL_4_3:
    case SPV_ENV_OPENGL_4_5:
    case SPV_ENV_UNIVERSAL_1_2:
    case SPV_ENV_UNIVERSAL_1_3:
    case SPV_ENV_VULKAN_1_1:
    case SPV_ENV_WEBGPU_0:
    case SPV_ENV_UNIVERSAL_1_4:
    case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
      return false;
    case SPV_ENV_OPENCL_1_2:
    case SPV_ENV_OPENCL_EMBEDDED_1_2:
    case SPV_ENV_OPENCL_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_1:
    case SPV_ENV_OPENCL_EMBEDDED_2_2:
    case SPV_ENV_OPENCL_2_1:
    case SPV_ENV_OPENCL_2_2:
      return true;
  }
  return false;
}

bool spvIsWebGPUEnv(spv_target_env env) {
  switch (env) {
    case SPV_ENV_UNIVERSAL_1_0:
    case SPV_ENV_VULKAN_1_0:
    case SPV_ENV_UNIVERSAL_1_1:
    case SPV_ENV_OPENGL_4_0:
    case SPV_ENV_OPENGL_4_1:
    case SPV_ENV_OPENGL_4_2:
    case SPV_ENV_OPENGL_4_3:
    case SPV_ENV_OPENGL_4_5:
    case SPV_ENV_UNIVERSAL_1_2:
    case SPV_ENV_UNIVERSAL_1_3:
    case SPV_ENV_VULKAN_1_1:
    case SPV_ENV_OPENCL_1_2:
    case SPV_ENV_OPENCL_EMBEDDED_1_2:
    case SPV_ENV_OPENCL_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_1:
    case SPV_ENV_OPENCL_EMBEDDED_2_2:
    case SPV_ENV_OPENCL_2_1:
    case SPV_ENV_OPENCL_2_2:
    case SPV_ENV_UNIVERSAL_1_4:
    case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
      return false;
    case SPV_ENV_WEBGPU_0:
      return true;
  }
  return false;
}

bool spvIsVulkanOrWebGPUEnv(spv_target_env env) {
  return spvIsVulkanEnv(env) || spvIsWebGPUEnv(env);
}

std::string spvLogStringForEnv(spv_target_env env) {
  switch (env) {
    case SPV_ENV_OPENCL_1_2:
    case SPV_ENV_OPENCL_2_0:
    case SPV_ENV_OPENCL_2_1:
    case SPV_ENV_OPENCL_2_2:
    case SPV_ENV_OPENCL_EMBEDDED_1_2:
    case SPV_ENV_OPENCL_EMBEDDED_2_0:
    case SPV_ENV_OPENCL_EMBEDDED_2_1:
    case SPV_ENV_OPENCL_EMBEDDED_2_2: {
      return "OpenCL";
    }
    case SPV_ENV_OPENGL_4_0:
    case SPV_ENV_OPENGL_4_1:
    case SPV_ENV_OPENGL_4_2:
    case SPV_ENV_OPENGL_4_3:
    case SPV_ENV_OPENGL_4_5: {
      return "OpenGL";
    }
    case SPV_ENV_VULKAN_1_0:
    case SPV_ENV_VULKAN_1_1:
    case SPV_ENV_VULKAN_1_1_SPIRV_1_4: {
      return "Vulkan";
    }
    case SPV_ENV_WEBGPU_0: {
      return "WebGPU";
    }
    case SPV_ENV_UNIVERSAL_1_0:
    case SPV_ENV_UNIVERSAL_1_1:
    case SPV_ENV_UNIVERSAL_1_2:
    case SPV_ENV_UNIVERSAL_1_3:
    case SPV_ENV_UNIVERSAL_1_4: {
      return "Universal";
    }
  }
  return "Unknown";
}

std::string spvTargetEnvList(const int pad, const int wrap) {
  std::string ret;
  size_t max_line_len = wrap - pad;  // The first line isn't padded
  std::string line;
  std::string sep = "";

  for (auto& name_env : spvTargetEnvNameMap) {
    std::string word = sep + name_env.first;
    if (line.length() + word.length() > max_line_len) {
      // Adding one word wouldn't fit, commit the line in progress and
      // start a new one.
      ret += line + "\n";
      line.assign(pad, ' ');
      // The first line is done. The max length now comprises the
      // padding.
      max_line_len = wrap;
    }
    line += word;
    sep = "|";
  }

  ret += line;

  return ret;
}
<|endoftext|>


<commit_before>#define BOOST_TEST_MAIN
#if !defined( WIN32 )
    #define BOOST_TEST_DYN_LINK
#endif
#define BOOST_TEST_MODULE Future2Tests

#include <boost/mpl/list.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>

/* For symbol_thingey */
#define BOOST_CHRONO_VERSION 2
#include <boost/chrono/chrono.hpp>
#include <boost/chrono/chrono_io.hpp>

#define FUTURE_TRACE 0

#include <cps/future.h>
#include "Log.h"

using namespace cps;
using namespace std;

BOOST_AUTO_TEST_CASE(leaf_future_string)
{
	{ /* shared_ptr interface means this is about as far as we can get with these: */
		future<int> f { };
		BOOST_CHECK(!f.is_ready());
		BOOST_CHECK(!f.is_done());
		BOOST_CHECK(!f.is_failed());
		BOOST_CHECK(!f.is_cancelled());
	}
	auto f = future<int>::create_shared();
	auto f2 = f->done(445)->on_done([](int v) {
		BOOST_CHECK_EQUAL(v, 445);
		cout << "Have value " << v << endl;
	})->then<string>([](int v) {
		BOOST_CHECK_EQUAL(v, 445);
		cout << "Value is still " << v << endl;
		return future<string>::create_shared();
	})->on_done([](string v) {
		BOOST_CHECK_EQUAL(v, "test");
		cout << "New futue is " << v << endl;
	})->done("test")->on_done([](string v) {
		BOOST_CHECK_EQUAL(v, "test");
		cout << "Finally " << v << endl;
	})->on_done([](const string &v) {
		BOOST_CHECK_EQUAL(v, "test");
		cout << "Alternatively " << v << endl;
	});
}

typedef boost::mpl::list<
	int,
	uint8_t, int8_t,
	uint16_t, int16_t,
	uint32_t, int32_t,
	uint64_t, int64_t,
	short, int, long, long long,
	float, double
> leaf_integral_types;
BOOST_AUTO_TEST_CASE_TEMPLATE(leaf_future_integral, T, leaf_integral_types)
{
	{
		auto f = future<T>::create_shared();
		BOOST_CHECK(!f->is_ready());
		BOOST_CHECK(!f->is_done());
		BOOST_CHECK(!f->is_failed());
		BOOST_CHECK(!f->is_cancelled());
		// Pick a smallish number that fits all the numeric types
		f->done(17)->on_done([](T v) {
			BOOST_CHECK_EQUAL(v, 17);
			cout << "Have value " << v << endl;
		});
		BOOST_CHECK( f->is_ready());
		BOOST_CHECK( f->is_done());
		BOOST_CHECK(!f->is_failed());
		BOOST_CHECK(!f->is_cancelled());
	}
	{
		auto f = future<T>::create_shared();
		BOOST_CHECK(!f->is_ready());
		BOOST_CHECK(!f->is_done());
		BOOST_CHECK(!f->is_failed());
		BOOST_CHECK(!f->is_cancelled());
		// Pick a smallish number that fits all the numeric types
		f->fail("some problem")->on_fail([](const std::string &err) {
			BOOST_CHECK_EQUAL(err, "some problem");
		});
		BOOST_CHECK( f->is_ready());
		BOOST_CHECK(!f->is_done());
		BOOST_CHECK( f->is_failed());
		BOOST_CHECK(!f->is_cancelled());
	}
}

BOOST_AUTO_TEST_CASE_TEMPLATE(leaf_future_other, T, boost::mpl::list<
	bool
>)
{
	auto f = future<T>::create_shared();
	BOOST_CHECK(!f->is_ready());
	BOOST_CHECK(!f->is_done());
	BOOST_CHECK(!f->is_failed());
	BOOST_CHECK(!f->is_cancelled());
	f->done(true);
	BOOST_CHECK( f->is_ready());
	BOOST_CHECK( f->is_done());
	BOOST_CHECK(!f->is_failed());
	BOOST_CHECK(!f->is_cancelled());
}

BOOST_AUTO_TEST_CASE(composition_needs_all)
{
	{
		auto f1 = future<int>::create_shared();
		auto f2 = future<string>::create_shared();

		auto composed = needs_all(
			f1,
			f2
		);
		composed->on_ready([](future<int> &f) {
			cout << "ready" << endl;
		});
		BOOST_CHECK(!composed->is_ready());
		f1->done(432);
		BOOST_CHECK(!composed->is_ready());
		f2->done("test");
		BOOST_CHECK( composed->is_ready());
		BOOST_CHECK( composed->is_done());
	}
	{
		auto f1 = future<int>::create_shared();
		auto f2 = future<string>::create_shared();

		auto composed = needs_all(
			f1,
			f2
		);
		composed->on_ready([](future<int> &f) {
			BOOST_CHECK(f.is_ready());
		});
		BOOST_CHECK(!composed->is_ready());
		f1->fail("aiee");
		BOOST_CHECK( composed->is_ready());
		BOOST_CHECK( composed->is_failed());
	}
	{
		std::vector<std::shared_ptr<future<int>>> pending {
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared()
		};

		auto composed = needs_all(
			pending
		);
		composed->on_ready([](future<int> &f) {
			BOOST_CHECK(f.is_ready());
		});
		BOOST_CHECK(!composed->is_ready());
		int i = 0;
		for(auto &it : pending) {
			it->done(++i);
			if(i == pending.size()) {
				BOOST_CHECK( composed->is_done());
			} else {
				BOOST_CHECK(!composed->is_ready());
			}
		}
		BOOST_CHECK( composed->is_ready());
	}
}

BOOST_AUTO_TEST_CASE(composition_needs_any)
{
	{
		auto f1 = future<int>::create_shared();
		auto f2 = future<string>::create_shared();

		auto composed = needs_all(
			f1,
			f2
		);
		composed->on_ready([](future<int> &f) {
			cout << "ready" << endl;
		});
		BOOST_CHECK(!composed->is_ready());
		f1->done(432);
		BOOST_CHECK(!composed->is_ready());
		f2->done("test");
		BOOST_CHECK( composed->is_ready());
		BOOST_CHECK( composed->is_done());
	}
	{
		auto f1 = future<int>::create_shared();
		auto f2 = future<string>::create_shared();

		auto composed = needs_all(
			f1,
			f2
		);
		composed->on_ready([](future<int> &f) {
			BOOST_CHECK(f.is_ready());
		});
		BOOST_CHECK(!composed->is_ready());
		f1->fail("aiee");
		BOOST_CHECK( composed->is_ready());
		BOOST_CHECK( composed->is_failed());
	}
	{
		std::vector<std::shared_ptr<future<int>>> pending {
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared()
		};

		auto composed = needs_all(
			pending
		);
		composed->on_ready([](future<int> &f) {
			BOOST_CHECK(f.is_ready());
		});
		BOOST_CHECK(!composed->is_ready());
		int i = 0;
		for(auto &it : pending) {
			it->done(++i);
			if(i == pending.size()) {
				BOOST_CHECK( composed->is_done());
			} else {
				BOOST_CHECK(!composed->is_ready());
			}
		}
		BOOST_CHECK( composed->is_ready());
	}
}

<commit_msg>Updated tests<commit_after>#define BOOST_TEST_MAIN
#if !defined( WIN32 )
    #define BOOST_TEST_DYN_LINK
#endif
#define BOOST_TEST_MODULE FutureTests

#include <boost/mpl/list.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>

/* For symbol_thingey */
#define BOOST_CHRONO_VERSION 2
#include <boost/chrono/chrono.hpp>
#include <boost/chrono/chrono_io.hpp>

#define FUTURE_TRACE 0

#include <cps/future.h>
#include "Log.h"

using namespace cps;
using namespace std;

BOOST_AUTO_TEST_CASE(future_string)
{
	{ /* shared_ptr interface means this is about as far as we can get with these: */
		future<int> f { };
		BOOST_CHECK(!f.is_ready());
		BOOST_CHECK(!f.is_done());
		BOOST_CHECK(!f.is_failed());
		BOOST_CHECK(!f.is_cancelled());
	}
	auto f = future<int>::create_shared();
	auto f2 = f->done(445)->on_done([](int v) {
		BOOST_CHECK_EQUAL(v, 445);
		cout << "Have value " << v << endl;
	})->then<string>([](int v) {
		BOOST_CHECK_EQUAL(v, 445);
		cout << "Value is still " << v << endl;
		return future<string>::create_shared();
	})->on_done([](string v) {
		BOOST_CHECK_EQUAL(v, "test");
		cout << "New futue is " << v << endl;
	})->done("test")->on_done([](string v) {
		BOOST_CHECK_EQUAL(v, "test");
		cout << "Finally " << v << endl;
	})->on_done([](const string &v) {
		BOOST_CHECK_EQUAL(v, "test");
		cout << "Alternatively " << v << endl;
	});
}

typedef boost::mpl::list<
	int,
	uint8_t, int8_t,
	uint16_t, int16_t,
	uint32_t, int32_t,
	uint64_t, int64_t,
	short, int, long, long long,
	float, double
> integral_types;
BOOST_AUTO_TEST_CASE_TEMPLATE(future_integral, T, integral_types)
{
	{
		auto f = future<T>::create_shared();
		BOOST_CHECK(!f->is_ready());
		BOOST_CHECK(!f->is_done());
		BOOST_CHECK(!f->is_failed());
		BOOST_CHECK(!f->is_cancelled());
		// Pick a smallish number that fits all the numeric types
		f->done(17)->on_done([](T v) {
			BOOST_CHECK_EQUAL(v, 17);
			cout << "Have value " << v << endl;
		});
		BOOST_CHECK( f->is_ready());
		BOOST_CHECK( f->is_done());
		BOOST_CHECK(!f->is_failed());
		BOOST_CHECK(!f->is_cancelled());
	}
	{
		auto f = future<T>::create_shared();
		BOOST_CHECK(!f->is_ready());
		BOOST_CHECK(!f->is_done());
		BOOST_CHECK(!f->is_failed());
		BOOST_CHECK(!f->is_cancelled());
		// Pick a smallish number that fits all the numeric types
		f->fail("some problem")->on_fail([](const std::string &err) {
			BOOST_CHECK_EQUAL(err, "some problem");
		});
		BOOST_CHECK( f->is_ready());
		BOOST_CHECK(!f->is_done());
		BOOST_CHECK( f->is_failed());
		BOOST_CHECK(!f->is_cancelled());
	}
}

BOOST_AUTO_TEST_CASE_TEMPLATE(future_other, T, boost::mpl::list<
	bool
>)
{
	auto f = future<T>::create_shared();
	BOOST_CHECK(!f->is_ready());
	BOOST_CHECK(!f->is_done());
	BOOST_CHECK(!f->is_failed());
	BOOST_CHECK(!f->is_cancelled());
	f->done(true);
	BOOST_CHECK( f->is_ready());
	BOOST_CHECK( f->is_done());
	BOOST_CHECK(!f->is_failed());
	BOOST_CHECK(!f->is_cancelled());
}

BOOST_AUTO_TEST_CASE(future_then)
{
	auto f = future<int>::create_shared();
	shared_ptr<future<string>> str1;
	shared_ptr<future<bool>> bool1;
	auto f2 = f->then<string>([&str1](int v) {
		BOOST_CHECK_EQUAL(v, 23);
		str1 = future<string>::create_shared();
		return str1;
	})->then<bool>([&bool1](string v) {
		BOOST_CHECK_EQUAL(v, "testing");
		bool1 = future<bool>::create_shared();
		return bool1;
	})->on_ready([&str1](future<bool> &in) {
		BOOST_CHECK_EQUAL(str1->value(), "testing");
		BOOST_CHECK(in.value());
	});
	BOOST_CHECK(!str1);
	BOOST_CHECK(!bool1);
	f->done(23);
	BOOST_CHECK( str1);
	BOOST_CHECK(!bool1);
	str1->done("testing");
	BOOST_CHECK_EQUAL( str1->value(), "testing");
	BOOST_CHECK( bool1);
	bool1->done(true);
	BOOST_CHECK(bool1->value());
}

BOOST_AUTO_TEST_CASE(composition_needs_all)
{
	{
		auto f1 = future<int>::create_shared();
		auto f2 = future<string>::create_shared();

		auto composed = needs_all(
			f1,
			f2
		);
		composed->on_ready([](future<int> &f) {
			cout << "ready" << endl;
		});
		BOOST_CHECK(!composed->is_ready());
		f1->done(432);
		BOOST_CHECK(!composed->is_ready());
		f2->done("test");
		BOOST_CHECK( composed->is_ready());
		BOOST_CHECK( composed->is_done());
	}
	{
		auto f1 = future<int>::create_shared();
		auto f2 = future<string>::create_shared();

		auto composed = needs_all(
			f1,
			f2
		);
		composed->on_ready([](future<int> &f) {
			BOOST_CHECK(f.is_ready());
		});
		BOOST_CHECK(!composed->is_ready());
		f1->fail("aiee");
		BOOST_CHECK( composed->is_ready());
		BOOST_CHECK( composed->is_failed());
	}
	{
		std::vector<std::shared_ptr<future<int>>> pending {
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared()
		};

		auto composed = needs_all(
			pending
		);
		composed->on_ready([](future<int> &f) {
			BOOST_CHECK(f.is_ready());
		});
		BOOST_CHECK(!composed->is_ready());
		int i = 0;
		for(auto &it : pending) {
			it->done(++i);
			if(i == pending.size()) {
				BOOST_CHECK( composed->is_done());
			} else {
				BOOST_CHECK(!composed->is_ready());
			}
		}
		BOOST_CHECK( composed->is_ready());
	}
}

BOOST_AUTO_TEST_CASE(composition_needs_any)
{
	{
		auto f1 = future<int>::create_shared();
		auto f2 = future<string>::create_shared();

		auto composed = needs_any(
			f1,
			f2
		);
		composed->on_ready([](future<int> &f) {
			cout << "ready" << endl;
		});
		BOOST_CHECK(!composed->is_ready());
		f1->done(432);
		BOOST_CHECK( composed->is_ready());
		BOOST_CHECK( composed->is_done());
		f2->done("test");
		BOOST_CHECK( composed->is_ready());
		BOOST_CHECK( composed->is_done());
	}
	{
		auto f1 = future<int>::create_shared();
		auto f2 = future<string>::create_shared();

		auto composed = needs_all(
			f1,
			f2
		);
		composed->on_ready([](future<int> &f) {
			BOOST_CHECK(f.is_ready());
		});
		BOOST_CHECK(!composed->is_ready());
		f1->fail("aiee");
		BOOST_CHECK( composed->is_ready());
		BOOST_CHECK( composed->is_failed());
	}
	{
		std::vector<std::shared_ptr<future<int>>> pending {
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared(),
			future<int>::create_shared()
		};

		auto composed = needs_all(
			pending
		);
		composed->on_ready([](future<int> &f) {
			BOOST_CHECK(f.is_ready());
		});
		BOOST_CHECK(!composed->is_ready());
		int i = 0;
		for(auto &it : pending) {
			it->done(++i);
			if(i == pending.size()) {
				BOOST_CHECK( composed->is_done());
			} else {
				BOOST_CHECK(!composed->is_ready());
			}
		}
		BOOST_CHECK( composed->is_ready());
	}
}

<|endoftext|>


<commit_before>// Copyright (c) 2009 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 "base/nss_init.h"

#include <dlfcn.h>
#include <nss.h>
#include <plarena.h>
#include <prerror.h>
#include <prinit.h>

// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424
// until NSS 3.12.2 comes out and we update to it.
#define Lock FOO_NSS_Lock
#include <pk11pub.h>
#include <secmod.h>
#include <ssl.h>
#undef Lock

#include "base/file_util.h"
#include "base/logging.h"
#include "base/singleton.h"
#include "base/string_util.h"

namespace {

std::string GetDefaultConfigDirectory() {
  const char* home = getenv("HOME");
  if (home == NULL) {
    LOG(ERROR) << "$HOME is not set.";
    return "";
  }
  FilePath dir(home);
  dir = dir.AppendASCII(".pki").AppendASCII("nssdb");
  if (!file_util::CreateDirectory(dir)) {
    LOG(ERROR) << "Failed to create ~/.pki/nssdb directory.";
    return "";
  }
  return dir.value();
}

// Load nss's built-in root certs.
SECMODModule *InitDefaultRootCerts() {
  const char* kModulePath = "libnssckbi.so";
  char modparams[1024];
  snprintf(modparams, sizeof(modparams),
          "name=\"Root Certs\" library=\"%s\"", kModulePath);
  SECMODModule *root = SECMOD_LoadUserModule(modparams, NULL, PR_FALSE);
  if (root)
    return root;

  // Aw, snap.  Can't find/load root cert shared library.
  // This will make it hard to talk to anybody via https.
  NOTREACHED();
  return NULL;
}

// A singleton to initialize/deinitialize NSPR.
// Separate from the NSS singleton because we initialize NSPR on the UI thread.
class NSPRInitSingleton {
 public:
  NSPRInitSingleton() {
    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
  }

  ~NSPRInitSingleton() {
    PRStatus prstatus = PR_Cleanup();
    if (prstatus != PR_SUCCESS) {
      LOG(ERROR) << "PR_Cleanup failed; was NSPR initialized on wrong thread?";
    }
  }
};

class NSSInitSingleton {
 public:
  NSSInitSingleton() {
    base::EnsureNSPRInit();

    SECStatus status;
    std::string database_dir = GetDefaultConfigDirectory();
    if (!database_dir.empty()) {
      // Initialize with a persistant database (~/.pki/nssdb).
      // Use "sql:" which can be shared by multiple processes safely.
      status = NSS_InitReadWrite(
          StringPrintf("sql:%s", database_dir.c_str()).c_str());
    } else {
      LOG(WARNING) << "Initialize NSS without using a persistent database "
                   << "(~/.pki/nssdb).";
      status = NSS_NoDB_Init(".");
    }
    if (status != SECSuccess) {
      char buffer[513] = "Couldn't retrieve error";
      PRInt32 err_length = PR_GetErrorTextLength();
      if (err_length > 0 && static_cast<size_t>(err_length) < sizeof(buffer))
        PR_GetErrorText(buffer);

      NOTREACHED() << "Error initializing NSS: " << buffer;
    }

    // If we haven't initialized the password for the NSS databases,
    // initialize an empty-string password so that we don't need to
    // log in.
    PK11SlotInfo* slot = PK11_GetInternalKeySlot();
    if (slot) {
      if (PK11_NeedUserInit(slot))
        PK11_InitPin(slot, NULL, NULL);
      PK11_FreeSlot(slot);
    }

    root_ = InitDefaultRootCerts();

    NSS_SetDomesticPolicy();

    // Use late binding to avoid scary but benign warning
    // "Symbol `SSL_ImplementedCiphers' has different size in shared object,
    //  consider re-linking"
    const PRUint16* pSSL_ImplementedCiphers = static_cast<const PRUint16*>(
        dlsym(RTLD_DEFAULT, "SSL_ImplementedCiphers"));
    if (pSSL_ImplementedCiphers == NULL) {
      NOTREACHED() << "Can't get list of supported ciphers";
      return;
    }

    // Explicitly enable exactly those ciphers with keys of at least 80 bits
    for (int i = 0; i < SSL_NumImplementedCiphers; i++) {
      SSLCipherSuiteInfo info;
      if (SSL_GetCipherSuiteInfo(pSSL_ImplementedCiphers[i], &info,
                                 sizeof(info)) == SECSuccess) {
        SSL_CipherPrefSetDefault(pSSL_ImplementedCiphers[i],
                                 (info.effectiveKeyBits >= 80));
      }
    }

    // Enable SSL
    SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE);

    // All other SSL options are set per-session by SSLClientSocket.
  }

  ~NSSInitSingleton() {
    if (root_) {
      SECMOD_UnloadUserModule(root_);
      SECMOD_DestroyModule(root_);
      root_ = NULL;
    }

    // Have to clear the cache, or NSS_Shutdown fails with SEC_ERROR_BUSY
    SSL_ClearSessionCache();

    SECStatus status = NSS_Shutdown();
    if (status != SECSuccess) {
      // We LOG(INFO) because this failure is relatively harmless
      // (leaking, but we're shutting down anyway).
      LOG(INFO) << "NSS_Shutdown failed; see "
                   "http://code.google.com/p/chromium/issues/detail?id=4609";
    }

    PL_ArenaFinish();
  }

 private:
  SECMODModule *root_;
};

}  // namespace

namespace base {

void EnsureNSPRInit() {
  Singleton<NSPRInitSingleton>::get();
}

void EnsureNSSInit() {
  Singleton<NSSInitSingleton>::get();
}

}  // namespace base
<commit_msg>If NSS_InitReadWrite fails, fall back on NSS_NoDB_Init.<commit_after>// Copyright (c) 2008-2009 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 "base/nss_init.h"

#include <dlfcn.h>
#include <nss.h>
#include <plarena.h>
#include <prerror.h>
#include <prinit.h>

// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424
// until NSS 3.12.2 comes out and we update to it.
#define Lock FOO_NSS_Lock
#include <pk11pub.h>
#include <secmod.h>
#include <ssl.h>
#undef Lock

#include "base/file_util.h"
#include "base/logging.h"
#include "base/singleton.h"
#include "base/string_util.h"

namespace {

std::string GetDefaultConfigDirectory() {
  const char* home = getenv("HOME");
  if (home == NULL) {
    LOG(ERROR) << "$HOME is not set.";
    return "";
  }
  FilePath dir(home);
  dir = dir.AppendASCII(".pki").AppendASCII("nssdb");
  if (!file_util::CreateDirectory(dir)) {
    LOG(ERROR) << "Failed to create ~/.pki/nssdb directory.";
    return "";
  }
  return dir.value();
}

// Load nss's built-in root certs.
SECMODModule *InitDefaultRootCerts() {
  const char* kModulePath = "libnssckbi.so";
  char modparams[1024];
  snprintf(modparams, sizeof(modparams),
          "name=\"Root Certs\" library=\"%s\"", kModulePath);
  SECMODModule *root = SECMOD_LoadUserModule(modparams, NULL, PR_FALSE);
  if (root)
    return root;

  // Aw, snap.  Can't find/load root cert shared library.
  // This will make it hard to talk to anybody via https.
  NOTREACHED();
  return NULL;
}

// A singleton to initialize/deinitialize NSPR.
// Separate from the NSS singleton because we initialize NSPR on the UI thread.
class NSPRInitSingleton {
 public:
  NSPRInitSingleton() {
    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
  }

  ~NSPRInitSingleton() {
    PRStatus prstatus = PR_Cleanup();
    if (prstatus != PR_SUCCESS) {
      LOG(ERROR) << "PR_Cleanup failed; was NSPR initialized on wrong thread?";
    }
  }
};

class NSSInitSingleton {
 public:
  NSSInitSingleton() {
    base::EnsureNSPRInit();

    SECStatus status = SECFailure;
    std::string database_dir = GetDefaultConfigDirectory();
    if (!database_dir.empty()) {
      // Initialize with a persistant database (~/.pki/nssdb).
      // Use "sql:" which can be shared by multiple processes safely.
      status = NSS_InitReadWrite(
          StringPrintf("sql:%s", database_dir.c_str()).c_str());
      if (status != SECSuccess) {
        LOG(ERROR) << "Error initializing NSS with a persistent "
                      "databases: NSS error code " << PR_GetError();
      }
    }
    if (status != SECSuccess) {
      LOG(WARNING) << "Initialize NSS without a persistent database "
                      "(~/.pki/nssdb).";
      status = NSS_NoDB_Init(NULL);
      if (status != SECSuccess) {
        LOG(ERROR) << "Error initializing NSS without a persistent "
                      "database: NSS error code " << PR_GetError();
      }
    }

    // If we haven't initialized the password for the NSS databases,
    // initialize an empty-string password so that we don't need to
    // log in.
    PK11SlotInfo* slot = PK11_GetInternalKeySlot();
    if (slot) {
      if (PK11_NeedUserInit(slot))
        PK11_InitPin(slot, NULL, NULL);
      PK11_FreeSlot(slot);
    }

    root_ = InitDefaultRootCerts();

    NSS_SetDomesticPolicy();

    // Use late binding to avoid scary but benign warning
    // "Symbol `SSL_ImplementedCiphers' has different size in shared object,
    //  consider re-linking"
    const PRUint16* pSSL_ImplementedCiphers = static_cast<const PRUint16*>(
        dlsym(RTLD_DEFAULT, "SSL_ImplementedCiphers"));
    if (pSSL_ImplementedCiphers == NULL) {
      NOTREACHED() << "Can't get list of supported ciphers";
      return;
    }

    // Explicitly enable exactly those ciphers with keys of at least 80 bits
    for (int i = 0; i < SSL_NumImplementedCiphers; i++) {
      SSLCipherSuiteInfo info;
      if (SSL_GetCipherSuiteInfo(pSSL_ImplementedCiphers[i], &info,
                                 sizeof(info)) == SECSuccess) {
        SSL_CipherPrefSetDefault(pSSL_ImplementedCiphers[i],
                                 (info.effectiveKeyBits >= 80));
      }
    }

    // Enable SSL
    SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE);

    // All other SSL options are set per-session by SSLClientSocket.
  }

  ~NSSInitSingleton() {
    if (root_) {
      SECMOD_UnloadUserModule(root_);
      SECMOD_DestroyModule(root_);
      root_ = NULL;
    }

    // Have to clear the cache, or NSS_Shutdown fails with SEC_ERROR_BUSY
    SSL_ClearSessionCache();

    SECStatus status = NSS_Shutdown();
    if (status != SECSuccess) {
      // We LOG(INFO) because this failure is relatively harmless
      // (leaking, but we're shutting down anyway).
      LOG(INFO) << "NSS_Shutdown failed; see "
                   "http://code.google.com/p/chromium/issues/detail?id=4609";
    }

    PL_ArenaFinish();
  }

 private:
  SECMODModule *root_;
};

}  // namespace

namespace base {

void EnsureNSPRInit() {
  Singleton<NSPRInitSingleton>::get();
}

void EnsureNSSInit() {
  Singleton<NSSInitSingleton>::get();
}

}  // namespace base
<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2015 Google Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and/or associated documentation files (the
 * "Materials"), to deal in the Materials without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Materials, and to
 * permit persons to whom the Materials are furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice(s) and this permission notice shall be
 * included in all copies or substantial portions of the Materials.
 *
 * The Materials are Confidential Information as defined by the
 * Khronos Membership Agreement until designated non-confidential by
 * Khronos, at which point this condition clause shall be removed.
 *
 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 *
 *//*!
 * \file
 * \brief Utility for pre-compiling source programs to SPIR-V
 *//*--------------------------------------------------------------------*/

#include "tcuDefs.hpp"
#include "tcuCommandLine.hpp"
#include "tcuPlatform.hpp"
#include "tcuResource.hpp"
#include "tcuTestLog.hpp"
#include "tcuTestHierarchyIterator.hpp"
#include "deUniquePtr.hpp"
#include "vkPrograms.hpp"
#include "vkBinaryRegistry.hpp"
#include "vktTestCase.hpp"
#include "vktTestPackage.hpp"
#include "deUniquePtr.hpp"
#include "deCommandLine.hpp"

#include <iostream>

namespace vkt
{

using std::vector;
using std::string;
using de::UniquePtr;

tcu::TestPackageRoot* createRoot (tcu::TestContext& testCtx)
{
	vector<tcu::TestNode*>	children;
	children.push_back(new TestPackage(testCtx));
	return new tcu::TestPackageRoot(testCtx, children);
}

enum BuildMode
{
	BUILDMODE_BUILD = 0,
	BUILDMODE_VERIFY,

	BUILDMODE_LAST
};

struct BuildStats
{
	int		numSucceeded;
	int		numFailed;

	BuildStats (void)
		: numSucceeded	(0)
		, numFailed		(0)
	{
	}
};

BuildStats buildPrograms (tcu::TestContext& testCtx, const std::string& dstPath, BuildMode mode)
{
	const UniquePtr<tcu::TestPackageRoot>	root		(createRoot(testCtx));
	tcu::DefaultHierarchyInflater			inflater	(testCtx);
	tcu::TestHierarchyIterator				iterator	(*root, inflater, testCtx.getCommandLine());
	const tcu::DirArchive					srcArchive	(dstPath.c_str());
	UniquePtr<vk::BinaryRegistryWriter>		writer		(mode == BUILDMODE_BUILD	? new vk::BinaryRegistryWriter(dstPath)			: DE_NULL);
	UniquePtr<vk::BinaryRegistryReader>		reader		(mode == BUILDMODE_VERIFY	? new vk::BinaryRegistryReader(srcArchive, "")	: DE_NULL);
	BuildStats								stats;

	while (iterator.getState() != tcu::TestHierarchyIterator::STATE_FINISHED)
	{
		if (iterator.getState() == tcu::TestHierarchyIterator::STATE_ENTER_NODE &&
			tcu::isTestNodeTypeExecutable(iterator.getNode()->getNodeType()))
		{
			const TestCase* const		testCase	= dynamic_cast<TestCase*>(iterator.getNode());
			const string				casePath	= iterator.getNodePath();
			vk::SourceCollection		progs;

			tcu::print("%s\n", casePath.c_str());

			testCase->initPrograms(progs);

			for (vk::SourceCollection::Iterator progIter = progs.begin(); progIter != progs.end(); ++progIter)
			{
				try
				{
					const vk::ProgramIdentifier			progId		(casePath, progIter.getName());
					glu::ShaderProgramInfo				buildInfo;
					const UniquePtr<vk::ProgramBinary>	binary		(vk::buildProgram(progIter.getProgram(), vk::PROGRAM_FORMAT_SPIRV, &buildInfo));

					if (mode == BUILDMODE_BUILD)
						writer->storeProgram(progId, *binary);
					else
					{
						DE_ASSERT(mode == BUILDMODE_VERIFY);

						const UniquePtr<vk::ProgramBinary>	storedBinary	(reader->loadProgram(progId));

						if (binary->getSize() != storedBinary->getSize())
							throw tcu::Exception("Binary size doesn't match");

						if (deMemCmp(binary->getBinary(), storedBinary->getBinary(), binary->getSize()))
							throw tcu::Exception("Binary contents don't match");
					}

					tcu::print("  OK: %s\n", progIter.getName().c_str());
					stats.numSucceeded += 1;
				}
				catch (const std::exception& e)
				{
					tcu::print("  ERROR: %s: %s\n", progIter.getName().c_str(), e.what());
					stats.numFailed += 1;
				}
			}
		}

		iterator.next();
	}

	return stats;
}

} // vkt

namespace opt
{

DE_DECLARE_COMMAND_LINE_OPT(DstPath,	std::string);
DE_DECLARE_COMMAND_LINE_OPT(Mode,		vkt::BuildMode);

} // opt

void registerOptions (de::cmdline::Parser& parser)
{
	using de::cmdline::Option;
	using de::cmdline::NamedValue;

	static const NamedValue<vkt::BuildMode> s_modes[] =
	{
		{ "build",	vkt::BUILDMODE_BUILD	},
		{ "verify",	vkt::BUILDMODE_VERIFY	}
	};

	parser << Option<opt::DstPath>	("d", "dst-path",	"Destination path",	".")
		   << Option<opt::Mode>		("m", "mode",		"Build mode",		s_modes,	"build");
}

int main (int argc, const char* argv[])
{
	de::cmdline::CommandLine	cmdLine;

	{
		de::cmdline::Parser		parser;
		registerOptions(parser);
		if (!parser.parse(argc, argv, &cmdLine, std::cerr))
		{
			parser.help(std::cout);
			return -1;
		}
	}

	try
	{
		const tcu::CommandLine	deqpCmdLine		("unused");
		tcu::DirArchive			archive			(".");
		tcu::TestLog			log				(deqpCmdLine.getLogFileName(), deqpCmdLine.getLogFlags());
		tcu::Platform			platform;
		tcu::TestContext		testCtx			(platform, archive, log, deqpCmdLine, DE_NULL);

		const vkt::BuildStats	stats			= vkt::buildPrograms(testCtx, cmdLine.getOption<opt::DstPath>(), cmdLine.getOption<opt::Mode>());

		tcu::print("DONE: %d passed, %d failed\n", stats.numSucceeded, stats.numFailed);

		return stats.numFailed == 0 ? 0 : -1;
	}
	catch (const std::exception& e)
	{
		tcu::die("%s", e.what());
	}
}
<commit_msg>Add --verbose option to vk-build-programs<commit_after>/*-------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2015 Google Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and/or associated documentation files (the
 * "Materials"), to deal in the Materials without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Materials, and to
 * permit persons to whom the Materials are furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice(s) and this permission notice shall be
 * included in all copies or substantial portions of the Materials.
 *
 * The Materials are Confidential Information as defined by the
 * Khronos Membership Agreement until designated non-confidential by
 * Khronos, at which point this condition clause shall be removed.
 *
 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 *
 *//*!
 * \file
 * \brief Utility for pre-compiling source programs to SPIR-V
 *//*--------------------------------------------------------------------*/

#include "tcuDefs.hpp"
#include "tcuCommandLine.hpp"
#include "tcuPlatform.hpp"
#include "tcuResource.hpp"
#include "tcuTestLog.hpp"
#include "tcuTestHierarchyIterator.hpp"
#include "deUniquePtr.hpp"
#include "vkPrograms.hpp"
#include "vkBinaryRegistry.hpp"
#include "vktTestCase.hpp"
#include "vktTestPackage.hpp"
#include "deUniquePtr.hpp"
#include "deCommandLine.hpp"

#include <iostream>

namespace vkt
{

using std::vector;
using std::string;
using de::UniquePtr;

tcu::TestPackageRoot* createRoot (tcu::TestContext& testCtx)
{
	vector<tcu::TestNode*>	children;
	children.push_back(new TestPackage(testCtx));
	return new tcu::TestPackageRoot(testCtx, children);
}

enum BuildMode
{
	BUILDMODE_BUILD = 0,
	BUILDMODE_VERIFY,

	BUILDMODE_LAST
};

struct BuildStats
{
	int		numSucceeded;
	int		numFailed;

	BuildStats (void)
		: numSucceeded	(0)
		, numFailed		(0)
	{
	}
};

BuildStats buildPrograms (tcu::TestContext& testCtx, const std::string& dstPath, BuildMode mode, bool verbose)
{
	const UniquePtr<tcu::TestPackageRoot>	root		(createRoot(testCtx));
	tcu::DefaultHierarchyInflater			inflater	(testCtx);
	tcu::TestHierarchyIterator				iterator	(*root, inflater, testCtx.getCommandLine());
	const tcu::DirArchive					srcArchive	(dstPath.c_str());
	UniquePtr<vk::BinaryRegistryWriter>		writer		(mode == BUILDMODE_BUILD	? new vk::BinaryRegistryWriter(dstPath)			: DE_NULL);
	UniquePtr<vk::BinaryRegistryReader>		reader		(mode == BUILDMODE_VERIFY	? new vk::BinaryRegistryReader(srcArchive, "")	: DE_NULL);
	BuildStats								stats;
	const bool								printLogs	= verbose;

	while (iterator.getState() != tcu::TestHierarchyIterator::STATE_FINISHED)
	{
		if (iterator.getState() == tcu::TestHierarchyIterator::STATE_ENTER_NODE &&
			tcu::isTestNodeTypeExecutable(iterator.getNode()->getNodeType()))
		{
			const TestCase* const		testCase	= dynamic_cast<TestCase*>(iterator.getNode());
			const string				casePath	= iterator.getNodePath();
			vk::SourceCollection		progs;

			tcu::print("%s\n", casePath.c_str());

			testCase->initPrograms(progs);

			for (vk::SourceCollection::Iterator progIter = progs.begin(); progIter != progs.end(); ++progIter)
			{
				glu::ShaderProgramInfo	buildInfo;

				try
				{
					const vk::ProgramIdentifier			progId		(casePath, progIter.getName());
					const UniquePtr<vk::ProgramBinary>	binary		(vk::buildProgram(progIter.getProgram(), vk::PROGRAM_FORMAT_SPIRV, &buildInfo));

					if (mode == BUILDMODE_BUILD)
						writer->storeProgram(progId, *binary);
					else
					{
						DE_ASSERT(mode == BUILDMODE_VERIFY);

						const UniquePtr<vk::ProgramBinary>	storedBinary	(reader->loadProgram(progId));

						if (binary->getSize() != storedBinary->getSize())
							throw tcu::Exception("Binary size doesn't match");

						if (deMemCmp(binary->getBinary(), storedBinary->getBinary(), binary->getSize()))
							throw tcu::Exception("Binary contents don't match");
					}

					tcu::print("  OK: %s\n", progIter.getName().c_str());
					stats.numSucceeded += 1;
				}
				catch (const std::exception& e)
				{
					tcu::print("  ERROR: %s: %s\n", progIter.getName().c_str(), e.what());

					if (printLogs)
					{
						for (size_t shaderNdx = 0; shaderNdx < buildInfo.shaders.size(); shaderNdx++)
						{
							const glu::ShaderInfo&	shaderInfo	= buildInfo.shaders[shaderNdx];
							const char* const		shaderName	= getShaderTypeName(shaderInfo.type);

							tcu::print("%s source:\n---\n%s\n---\n", shaderName, shaderInfo.source.c_str());
							tcu::print("%s compile log:\n---\n%s\n---\n", shaderName, shaderInfo.infoLog.c_str());
						}
					}

					stats.numFailed += 1;
				}
			}
		}

		iterator.next();
	}

	return stats;
}

} // vkt

namespace opt
{

DE_DECLARE_COMMAND_LINE_OPT(DstPath,	std::string);
DE_DECLARE_COMMAND_LINE_OPT(Mode,		vkt::BuildMode);
DE_DECLARE_COMMAND_LINE_OPT(Verbose,	bool);

} // opt

void registerOptions (de::cmdline::Parser& parser)
{
	using de::cmdline::Option;
	using de::cmdline::NamedValue;

	static const NamedValue<vkt::BuildMode> s_modes[] =
	{
		{ "build",	vkt::BUILDMODE_BUILD	},
		{ "verify",	vkt::BUILDMODE_VERIFY	}
	};

	parser << Option<opt::DstPath>	("d", "dst-path",	"Destination path",	"out")
		   << Option<opt::Mode>		("m", "mode",		"Build mode",		s_modes,	"build")
		   << Option<opt::Verbose>	("v", "verbose",	"Verbose output");
}

int main (int argc, const char* argv[])
{
	de::cmdline::CommandLine	cmdLine;

	{
		de::cmdline::Parser		parser;
		registerOptions(parser);
		if (!parser.parse(argc, argv, &cmdLine, std::cerr))
		{
			parser.help(std::cout);
			return -1;
		}
	}

	try
	{
		const tcu::CommandLine	deqpCmdLine		("unused");
		tcu::DirArchive			archive			(".");
		tcu::TestLog			log				(deqpCmdLine.getLogFileName(), deqpCmdLine.getLogFlags());
		tcu::Platform			platform;
		tcu::TestContext		testCtx			(platform, archive, log, deqpCmdLine, DE_NULL);

		const vkt::BuildStats	stats			= vkt::buildPrograms(testCtx,
																	 cmdLine.getOption<opt::DstPath>(),
																	 cmdLine.getOption<opt::Mode>(),
																	 cmdLine.getOption<opt::Verbose>());

		tcu::print("DONE: %d passed, %d failed\n", stats.numSucceeded, stats.numFailed);

		return stats.numFailed == 0 ? 0 : -1;
	}
	catch (const std::exception& e)
	{
		tcu::die("%s", e.what());
	}
}
<|endoftext|>


<commit_before>//$Id: ResultsPostProcessor.h 3456 2013-06-26 02:11:13Z Jamshid $

/*
 * The Software is made available solely for use according to the License Agreement. Any reproduction
 * or redistribution of the Software not in accordance with the License Agreement is expressly prohibited
 * by law, and may result in severe civil and criminal penalties. Violators will be prosecuted to the
 * maximum extent possible.
 *
 * THE SOFTWARE IS WARRANTED, IF AT ALL, ONLY ACCORDING TO THE TERMS OF THE LICENSE AGREEMENT. EXCEPT
 * AS WARRANTED IN THE LICENSE AGREEMENT, SRCH2 INC. HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS WITH
 * REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT.  IN NO EVENT SHALL SRCH2 INC. BE LIABLE FOR ANY
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF SOFTWARE.

 * Copyright © 2010 SRCH2 Inc. All rights reserved
 */

#include "FacetedSearchFilterInternal.h"
#include <vector>
#include <map>
#include <string>
#include <algorithm>
#include "util/Assert.h"
#include "instantsearch/Score.h"

using namespace std;
namespace srch2 {
namespace instantsearch {

void FacetedSearchFilterInternal::doAggregationCategorical(const Score & attributeValue,
        std::map<string , float > * counts) {

    // move on computed facet results to see if this value is seen before (increment) or is new (add and initialize)
	std::string attributeValueLowerCase = attributeValue.toString();
	std::transform(attributeValueLowerCase.begin(), attributeValueLowerCase.end(), attributeValueLowerCase.begin(), ::tolower);
    std::map<string , float >::iterator p = counts->find(attributeValueLowerCase);
    if( p != counts->end()){
        p->second ++;
        return;
    }
    // not found in map, initialization with 1
    (*counts)[attributeValueLowerCase] = 1;
    return;
}

// Range facet
void FacetedSearchFilterInternal::doAggregationRange(const Score & attributeValue,
        const std::vector<Score> & lowerBounds,
        std::vector<pair<string, float> > * counts  , Score & start, Score & end, Score & gap) {

    unsigned groupId = attributeValue.findIndexOfContainingInterval(start,end, gap);
    if(groupId == -1){
        return;
    }
    if(groupId >= counts->size()){
        groupId =  counts->size() - 1;
    }
    counts->at(groupId).second ++ ;
    return;
}

/*
 * Example :
 * If we have two attributes : price,model (facet type : range, categorical)
 * and start,end and gap for price are 1,100 and 10. Then this function
 * produces an empty vector for model (because it's categorical) and a vector with the following
 * values for price:
 * -large_value, 1, 11, 21, 31, 41, ..., 91, 101
 */
void FacetedSearchFilterInternal::prepareFacetInputs(IndexSearcher *indexSearcher) {

    if(isPrepared){
        return;
    }else{
        isPrepared = true;
    }

    IndexSearcherInternal * indexSearcherInternal =
            dynamic_cast<IndexSearcherInternal *>(indexSearcher);
    Schema * schema = indexSearcherInternal->getSchema();
    ForwardIndex * forwardIndex = indexSearcherInternal->getForwardIndex();

    // 1. parse the values into Score.
    unsigned fieldIndex = 0;
    for (std::vector<std::string>::iterator field = this->fields.begin();
            field != this->fields.end(); ++field) {
        if (this->facetTypes.at(fieldIndex) == FacetTypeCategorical) { // Simple facet
            Score placeHolder; // just insert placeholders
            rangeStartScores.push_back(placeHolder);
            rangeEndScores.push_back(placeHolder);
            rangeGapScores.push_back(placeHolder);
        } else { // Range facet
            FilterType attributeType = schema->getTypeOfNonSearchableAttribute(
                    schema->getNonSearchableAttributeId(*field));
            Score start;
            start.setScore(attributeType, this->rangeStarts.at(fieldIndex));

            Score end;
            end.setScore(attributeType, this->rangeEnds.at(fieldIndex));

            Score gap;
            if(attributeType == ATTRIBUTE_TYPE_TIME){
            	// For time attributes gap should not be of the same type, it should be
            	// of type TimeDuration.
            	if(start > end){ // start should not be greater than end
            		start = end;
            		gap.setScore(ATTRIBUTE_TYPE_DURATION, "00:00:00");
            	}else{
            		gap.setScore(ATTRIBUTE_TYPE_DURATION, this->rangeGaps.at(fieldIndex));
            	}
            }else{
            	if(start > end){ // start should not be greater than end
            		start = end;
            		gap.setScore(attributeType , "0");
            	}else{
            		gap.setScore(attributeType, this->rangeGaps.at(fieldIndex));
            	}
            }

            rangeStartScores.push_back(start);
            rangeEndScores.push_back(end);
            rangeGapScores.push_back(gap);

        }

        //
        fieldIndex++;
    }

    // 2. create the lowerbound vector for each attribute

    unsigned facetTypeIndex = 0;
    for (std::vector<FacetType>::iterator facetTypeIterator = facetTypes.begin();
            facetTypeIterator != facetTypes.end(); ++facetTypeIterator) {

        std::vector<Score> lowerBounds;
		Score & start = rangeStartScores.at(facetTypeIndex);
		Score & end = rangeEndScores.at(facetTypeIndex);
		Score & gap = rangeGapScores.at(facetTypeIndex);
		Score lowerBoundToAdd = start;
        switch (*facetTypeIterator) {
        case FacetTypeCategorical: // lower bounds vector is empty, because lower bounds are not determined before results
            break;

        case FacetTypeRange:
            ASSERT(start.getType() != srch2::instantsearch::ATTRIBUTE_TYPE_TEXT);

            // Example : start : 1, gap : 10 , end : 100
            // first -large_value is added as the first category
            // then 1, 11, 21, ...and 91 are added in the loop.
            // and 101 is added after loop.
            lowerBounds.push_back(lowerBoundToAdd.minimumValue()); // to collect data smaller than start
            while (lowerBoundToAdd < end) {
                lowerBounds.push_back(lowerBoundToAdd); // data of normal categories
                lowerBoundToAdd = lowerBoundToAdd + gap;
            }
            lowerBounds.push_back(end); // to collect data greater than end
            break;
        default:
        	ASSERT(false);
        	break;
        }
        lowerBoundsOfIntervals[fields.at(facetTypeIndex)] = lowerBounds;
        //
        facetTypeIndex++;
    }

}

}
}
<commit_msg>A bug is fixed.<commit_after>//$Id: ResultsPostProcessor.h 3456 2013-06-26 02:11:13Z Jamshid $

/*
 * The Software is made available solely for use according to the License Agreement. Any reproduction
 * or redistribution of the Software not in accordance with the License Agreement is expressly prohibited
 * by law, and may result in severe civil and criminal penalties. Violators will be prosecuted to the
 * maximum extent possible.
 *
 * THE SOFTWARE IS WARRANTED, IF AT ALL, ONLY ACCORDING TO THE TERMS OF THE LICENSE AGREEMENT. EXCEPT
 * AS WARRANTED IN THE LICENSE AGREEMENT, SRCH2 INC. HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS WITH
 * REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT.  IN NO EVENT SHALL SRCH2 INC. BE LIABLE FOR ANY
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF SOFTWARE.

 * Copyright © 2010 SRCH2 Inc. All rights reserved
 */

#include "FacetedSearchFilterInternal.h"
#include <vector>
#include <map>
#include <string>
#include <algorithm>
#include "util/Assert.h"
#include "instantsearch/Score.h"

using namespace std;
namespace srch2 {
namespace instantsearch {

void FacetedSearchFilterInternal::doAggregationCategorical(const Score & attributeValue,
        std::map<string , float > * counts) {

    // move on computed facet results to see if this value is seen before (increment) or is new (add and initialize)
	std::string attributeValueLowerCase = attributeValue.toString();
	std::transform(attributeValueLowerCase.begin(), attributeValueLowerCase.end(), attributeValueLowerCase.begin(), ::tolower);
    std::map<string , float >::iterator p = counts->find(attributeValueLowerCase);
    if( p != counts->end()){
        p->second ++;
        return;
    }
    // not found in map, initialization with 1
    (*counts)[attributeValueLowerCase] = 1;
    return;
}

// Range facet
void FacetedSearchFilterInternal::doAggregationRange(const Score & attributeValue,
        const std::vector<Score> & lowerBounds,
        std::vector<pair<string, float> > * counts  , Score & start, Score & end, Score & gap) {

	// the reason for this is that the interval right before end can be smaller than gap. So the formula used in
	// findIndexOfContainingInterval will return a wrong index.
	// example:
	// start = 0 ; gap = 6; end = 10
	// intervals will be (*,0) , [0,6), [6,10), [10,*)
	// interval [6,10) is smaller than gap. now if we use formula (value - start ) / gap + 1
	// for 10 or 11, it returns 2 which is wrong.
	if(attributeValue >= end){
		unsigned groupId =  counts->size() - 1;
	    counts->at(groupId).second ++ ;
	    return;
	}
    unsigned groupId = attributeValue.findIndexOfContainingInterval(start,end, gap);
    if(groupId == -1){
        return;
    }
    if(groupId >= counts->size()){
        groupId =  counts->size() - 1;
    }
    counts->at(groupId).second ++ ;
    return;
}

/*
 * Example :
 * If we have two attributes : price,model (facet type : range, categorical)
 * and start,end and gap for price are 1,100 and 10. Then this function
 * produces an empty vector for model (because it's categorical) and a vector with the following
 * values for price:
 * -large_value, 1, 11, 21, 31, 41, ..., 91, 101
 */
void FacetedSearchFilterInternal::prepareFacetInputs(IndexSearcher *indexSearcher) {

    if(isPrepared){
        return;
    }else{
        isPrepared = true;
    }

    IndexSearcherInternal * indexSearcherInternal =
            dynamic_cast<IndexSearcherInternal *>(indexSearcher);
    Schema * schema = indexSearcherInternal->getSchema();
    ForwardIndex * forwardIndex = indexSearcherInternal->getForwardIndex();

    // 1. parse the values into Score.
    unsigned fieldIndex = 0;
    for (std::vector<std::string>::iterator field = this->fields.begin();
            field != this->fields.end(); ++field) {
        if (this->facetTypes.at(fieldIndex) == FacetTypeCategorical) { // Simple facet
            Score placeHolder; // just insert placeholders
            rangeStartScores.push_back(placeHolder);
            rangeEndScores.push_back(placeHolder);
            rangeGapScores.push_back(placeHolder);
        } else { // Range facet
            FilterType attributeType = schema->getTypeOfNonSearchableAttribute(
                    schema->getNonSearchableAttributeId(*field));
            Score start;
            start.setScore(attributeType, this->rangeStarts.at(fieldIndex));

            Score end;
            end.setScore(attributeType, this->rangeEnds.at(fieldIndex));

            Score gap;
            if(attributeType == ATTRIBUTE_TYPE_TIME){
            	// For time attributes gap should not be of the same type, it should be
            	// of type TimeDuration.
            	if(start > end){ // start should not be greater than end
            		start = end;
            		gap.setScore(ATTRIBUTE_TYPE_DURATION, "00:00:00");
            	}else{
            		gap.setScore(ATTRIBUTE_TYPE_DURATION, this->rangeGaps.at(fieldIndex));
            	}
            }else{
            	if(start > end){ // start should not be greater than end
            		start = end;
            		gap.setScore(attributeType , "0");
            	}else{
            		gap.setScore(attributeType, this->rangeGaps.at(fieldIndex));
            	}
            }

            rangeStartScores.push_back(start);
            rangeEndScores.push_back(end);
            rangeGapScores.push_back(gap);

        }

        //
        fieldIndex++;
    }

    // 2. create the lowerbound vector for each attribute

    unsigned facetTypeIndex = 0;
    for (std::vector<FacetType>::iterator facetTypeIterator = facetTypes.begin();
            facetTypeIterator != facetTypes.end(); ++facetTypeIterator) {

        std::vector<Score> lowerBounds;
		Score & start = rangeStartScores.at(facetTypeIndex);
		Score & end = rangeEndScores.at(facetTypeIndex);
		Score & gap = rangeGapScores.at(facetTypeIndex);
		Score lowerBoundToAdd = start;
        switch (*facetTypeIterator) {
        case FacetTypeCategorical: // lower bounds vector is empty, because lower bounds are not determined before results
            break;

        case FacetTypeRange:
            ASSERT(start.getType() != srch2::instantsearch::ATTRIBUTE_TYPE_TEXT);

            // Example : start : 1, gap : 10 , end : 100
            // first -large_value is added as the first category
            // then 1, 11, 21, ...and 91 are added in the loop.
            // and 101 is added after loop.
            lowerBounds.push_back(lowerBoundToAdd.minimumValue()); // to collect data smaller than start
            while (lowerBoundToAdd < end) {
                lowerBounds.push_back(lowerBoundToAdd); // data of normal categories
                lowerBoundToAdd = lowerBoundToAdd + gap;
            }
            lowerBounds.push_back(end); // to collect data greater than end
            break;
        default:
        	ASSERT(false);
        	break;
        }
        lowerBoundsOfIntervals[fields.at(facetTypeIndex)] = lowerBounds;
        //
        facetTypeIndex++;
    }

}

}
}
<|endoftext|>


<commit_before>#include "ConfigActivationManager.h"
#include "System/Events/EventLoop.h"
#include "Application/Common/DatabaseConsts.h"
#include "Application/Common/ContextTransport.h"
#include "ConfigServer.h"
#include "ConfigQuorumProcessor.h"

void ConfigActivationManager::Init(ConfigServer* configServer_)
{
    configServer = configServer_;

    activationTimeout.SetCallable(MFUNC(ConfigActivationManager, OnActivationTimeout));
}

void ConfigActivationManager::TryDeactivateShardServer(uint64_t nodeID)
{
    ConfigState*        configState;
    ConfigQuorum*       itQuorum;
    ConfigShardServer*  shardServer;

    configState = configServer->GetDatabaseManager()->GetConfigState();

    FOREACH(itQuorum, configState->quorums)
    {
        if (itQuorum->isActivatingNode && itQuorum->activatingNodeID == nodeID)
        {
            shardServer = configState->GetShardServer(itQuorum->activatingNodeID);
            assert(shardServer != NULL);

            itQuorum->ClearActivation();
            UpdateTimeout();

            Log_Message("Activation failed for shard server %U and quorum %U...",
             itQuorum->quorumID, itQuorum->activatingNodeID);
        }

        if (itQuorum->IsActiveMember(nodeID))
        {
            // if this node was part of an activation process, cancel it
            if (itQuorum->isActivatingNode)
            {
                shardServer = configState->GetShardServer(itQuorum->activatingNodeID);
                assert(shardServer != NULL);

                itQuorum->ClearActivation();
                UpdateTimeout();

                Log_Message("Activation failed for shard server %U and quorum %U...",
                 itQuorum->activatingNodeID, itQuorum->quorumID);
            }

            configServer->GetQuorumProcessor()->DeactivateNode(itQuorum->quorumID, nodeID);
        }
    }
}

void ConfigActivationManager::TryActivateShardServer(uint64_t nodeID, bool force)
{
    uint64_t            paxosID;
    ConfigState*        configState;
    ConfigQuorum*       itQuorum;
    ConfigShardServer*  shardServer;
    uint64_t            now;

    now = EventLoop::Now();

    Log_Trace();

    configState = configServer->GetDatabaseManager()->GetConfigState();
    shardServer = configState->GetShardServer(nodeID);

    FOREACH(itQuorum, configState->quorums)
    {
        Log_Trace("itQuorum->isActivatingNode: %b", itQuorum->isActivatingNode);
        if (itQuorum->isActivatingNode)
            continue;

        Log_Trace("itQuorum->hasPrimary: %b", itQuorum->hasPrimary);
        if (!itQuorum->hasPrimary)
            continue;

        if (itQuorum->IsInactiveMember(nodeID))
        {
            paxosID = QuorumInfo::GetQuorumInfo(shardServer->quorumInfos, itQuorum->quorumID)->paxosID;
            if (paxosID >= (itQuorum->paxosID - RLOG_REACTIVATION_DIFF) ||
             itQuorum->paxosID <= RLOG_REACTIVATION_DIFF)
            {
                if (!force && !shardServer->tryAutoActivation)
                    continue;

                // the shard server is "almost caught up", start the activation process
                itQuorum->OnActivationStart(nodeID, now + ACTIVATION_TIMEOUT);
                UpdateTimeout();

                shardServer->tryAutoActivation = false;

                Log_Message("Activation started for shard server %U and quorum %U...",
                 itQuorum->activatingNodeID, itQuorum->quorumID);
                configServer->OnConfigStateChanged(false);
            }
        }
    }
}

void ConfigActivationManager::OnExtendLease(ConfigQuorum& quorum, ClusterMessage& message)
{
    ConfigState*        configState;
    ConfigShardServer*  shardServer;

    Log_Trace();

    if (!quorum.hasPrimary || message.nodeID != quorum.primaryID)
        return;

    configState = configServer->GetDatabaseManager()->GetConfigState();

    if (!quorum.isActivatingNode || quorum.isReplicatingActivation ||
     message.configID != quorum.configID)
    {
        Log_Trace("ExtendLease condition: %b %b %U %U", quorum.isActivatingNode,
        quorum.isReplicatingActivation,
        message.configID,
        quorum.configID);
        return;
    }

    if (!quorum.isWatchingPaxosID)
    {
        Log_Message("Activating shard server %U in quorum %U: Starting to monitor the primary's paxosID",
         quorum.quorumID, quorum.activatingNodeID);

        quorum.OnActivationMonitoring(message.paxosID);
        configServer->OnConfigStateChanged(false);
    }
    else
    {
        Log_Trace();

        // if the primary was able to increase its paxosID, the new shardserver joined successfully
        if (message.paxosID > quorum.activationPaxosID)
        {
            Log_Message("Activating shard server %U in quorum %U: The primary was able to increase its paxosID!",
             quorum.quorumID, quorum.activatingNodeID);

            quorum.OnActivationReplication();
            configServer->OnConfigStateChanged(false);
            configServer->GetQuorumProcessor()->ActivateNode(quorum.quorumID, quorum.activatingNodeID);

            shardServer = configState->GetShardServer(quorum.activatingNodeID);
            shardServer->tryAutoActivation = true;
        }
        else
        {
            Log_Message("Activating shard server %U in quorum %U: The primary was not able to increase its paxosID so far...",
             quorum.quorumID, quorum.activatingNodeID);
        }
    }
}

void ConfigActivationManager::OnActivationTimeout()
{
    uint64_t            now;
    ConfigState*        configState;
    ConfigQuorum*       itQuorum;
    ConfigShardServer*  shardServer;

    Log_Trace();

    now = EventLoop::Now();
    configState = configServer->GetDatabaseManager()->GetConfigState();

    FOREACH(itQuorum, configState->quorums)
    {
        if (itQuorum->activationExpireTime > 0 && itQuorum->activationExpireTime < now)
        {
            // stop activation

            assert(itQuorum->isActivatingNode == true);
            assert(itQuorum->isReplicatingActivation == false);

            shardServer = configState->GetShardServer(itQuorum->activatingNodeID);
            assert(shardServer != NULL);

            Log_Message("Activating shard server %U in quorum %U: Activation failed...",
             itQuorum->activatingNodeID, itQuorum->quorumID);

            itQuorum->ClearActivation();

            configServer->OnConfigStateChanged(false);
        }
    }

    UpdateTimeout();
}

void ConfigActivationManager::UpdateTimeout()
{
    ConfigQuorum*   it;
    uint64_t        activationExpireTime;

    Log_Trace();

    activationExpireTime = 0;
    FOREACH(it, configServer->GetDatabaseManager()->GetConfigState()->quorums)
    {
        if (it->isActivatingNode && !it->isReplicatingActivation)
        {
            if (activationExpireTime == 0 || it->activationExpireTime < activationExpireTime)
                activationExpireTime = it->activationExpireTime;
        }
    }

    if (activationExpireTime > 0)
    {
        activationTimeout.SetExpireTime(activationExpireTime);
        EventLoop::Reset(&activationTimeout);
    }
}
<commit_msg>Fixed Log_Debugs.<commit_after>#include "ConfigActivationManager.h"
#include "System/Events/EventLoop.h"
#include "Application/Common/DatabaseConsts.h"
#include "Application/Common/ContextTransport.h"
#include "ConfigServer.h"
#include "ConfigQuorumProcessor.h"

void ConfigActivationManager::Init(ConfigServer* configServer_)
{
    configServer = configServer_;

    activationTimeout.SetCallable(MFUNC(ConfigActivationManager, OnActivationTimeout));
}

void ConfigActivationManager::TryDeactivateShardServer(uint64_t nodeID)
{
    ConfigState*        configState;
    ConfigQuorum*       itQuorum;
    ConfigShardServer*  shardServer;

    configState = configServer->GetDatabaseManager()->GetConfigState();

    FOREACH(itQuorum, configState->quorums)
    {
        if (itQuorum->isActivatingNode && itQuorum->activatingNodeID == nodeID)
        {
            shardServer = configState->GetShardServer(itQuorum->activatingNodeID);
            assert(shardServer != NULL);

            itQuorum->ClearActivation();
            UpdateTimeout();

            Log_Message("Activation failed for shard server %U and quorum %U...",
             itQuorum->quorumID, itQuorum->activatingNodeID);
        }

        if (itQuorum->IsActiveMember(nodeID))
        {
            // if this node was part of an activation process, cancel it
            if (itQuorum->isActivatingNode)
            {
                shardServer = configState->GetShardServer(itQuorum->activatingNodeID);
                assert(shardServer != NULL);

                itQuorum->ClearActivation();
                UpdateTimeout();

                Log_Message("Activation failed for shard server %U and quorum %U...",
                 itQuorum->activatingNodeID, itQuorum->quorumID);
            }

            configServer->GetQuorumProcessor()->DeactivateNode(itQuorum->quorumID, nodeID);
        }
    }
}

void ConfigActivationManager::TryActivateShardServer(uint64_t nodeID, bool force)
{
    uint64_t            paxosID;
    ConfigState*        configState;
    ConfigQuorum*       itQuorum;
    ConfigShardServer*  shardServer;
    uint64_t            now;

    now = EventLoop::Now();

    Log_Trace();

    configState = configServer->GetDatabaseManager()->GetConfigState();
    shardServer = configState->GetShardServer(nodeID);

    FOREACH(itQuorum, configState->quorums)
    {
        Log_Trace("itQuorum->isActivatingNode: %b", itQuorum->isActivatingNode);
        if (itQuorum->isActivatingNode)
            continue;

        Log_Trace("itQuorum->hasPrimary: %b", itQuorum->hasPrimary);
        if (!itQuorum->hasPrimary)
            continue;

        if (itQuorum->IsInactiveMember(nodeID))
        {
            paxosID = QuorumInfo::GetQuorumInfo(shardServer->quorumInfos, itQuorum->quorumID)->paxosID;
            if (paxosID >= (itQuorum->paxosID - RLOG_REACTIVATION_DIFF) ||
             itQuorum->paxosID <= RLOG_REACTIVATION_DIFF)
            {
                if (!force && !shardServer->tryAutoActivation)
                    continue;

                // the shard server is "almost caught up", start the activation process
                itQuorum->OnActivationStart(nodeID, now + ACTIVATION_TIMEOUT);
                UpdateTimeout();

                shardServer->tryAutoActivation = false;

                Log_Message("Activation started for shard server %U and quorum %U...",
                 itQuorum->activatingNodeID, itQuorum->quorumID);
                configServer->OnConfigStateChanged(false);
            }
        }
    }
}

void ConfigActivationManager::OnExtendLease(ConfigQuorum& quorum, ClusterMessage& message)
{
    ConfigState*        configState;
    ConfigShardServer*  shardServer;

    Log_Trace();

    if (!quorum.hasPrimary || message.nodeID != quorum.primaryID)
        return;

    configState = configServer->GetDatabaseManager()->GetConfigState();

    if (!quorum.isActivatingNode || quorum.isReplicatingActivation ||
     message.configID != quorum.configID)
    {
        Log_Trace("ExtendLease condition: %b %b %U %U", quorum.isActivatingNode,
        quorum.isReplicatingActivation,
        message.configID,
        quorum.configID);
        return;
    }

    if (!quorum.isWatchingPaxosID)
    {
        Log_Message("Activating shard server %U in quorum %U: Starting to monitor the primary's paxosID",
         quorum.activatingNodeID, quorum.quorumID);

        quorum.OnActivationMonitoring(message.paxosID);
        configServer->OnConfigStateChanged(false);
    }
    else
    {
        Log_Trace();

        // if the primary was able to increase its paxosID, the new shardserver joined successfully
        if (message.paxosID > quorum.activationPaxosID)
        {
            Log_Message("Activating shard server %U in quorum %U: The primary was able to increase its paxosID!",
             quorum.activatingNodeID, quorum.quorumID);

            quorum.OnActivationReplication();
            configServer->OnConfigStateChanged(false);
            configServer->GetQuorumProcessor()->ActivateNode(quorum.quorumID, quorum.activatingNodeID);

            shardServer = configState->GetShardServer(quorum.activatingNodeID);
            shardServer->tryAutoActivation = true;
        }
        else
        {
            Log_Message("Activating shard server %U in quorum %U: The primary was not able to increase its paxosID so far...",
             quorum.activatingNodeID, quorum.quorumID);
        }
    }
}

void ConfigActivationManager::OnActivationTimeout()
{
    uint64_t            now;
    ConfigState*        configState;
    ConfigQuorum*       itQuorum;
    ConfigShardServer*  shardServer;

    Log_Trace();

    now = EventLoop::Now();
    configState = configServer->GetDatabaseManager()->GetConfigState();

    FOREACH(itQuorum, configState->quorums)
    {
        if (itQuorum->activationExpireTime > 0 && itQuorum->activationExpireTime < now)
        {
            // stop activation

            assert(itQuorum->isActivatingNode == true);
            assert(itQuorum->isReplicatingActivation == false);

            shardServer = configState->GetShardServer(itQuorum->activatingNodeID);
            assert(shardServer != NULL);

            Log_Message("Activating shard server %U in quorum %U: Activation failed...",
             itQuorum->activatingNodeID, itQuorum->quorumID);

            itQuorum->ClearActivation();

            configServer->OnConfigStateChanged(false);
        }
    }

    UpdateTimeout();
}

void ConfigActivationManager::UpdateTimeout()
{
    ConfigQuorum*   it;
    uint64_t        activationExpireTime;

    Log_Trace();

    activationExpireTime = 0;
    FOREACH(it, configServer->GetDatabaseManager()->GetConfigState()->quorums)
    {
        if (it->isActivatingNode && !it->isReplicatingActivation)
        {
            if (activationExpireTime == 0 || it->activationExpireTime < activationExpireTime)
                activationExpireTime = it->activationExpireTime;
        }
    }

    if (activationExpireTime > 0)
    {
        activationTimeout.SetExpireTime(activationExpireTime);
        EventLoop::Reset(&activationTimeout);
    }
}
<|endoftext|>


<commit_before>//=====================================================================//
/*!	@file
	@brief	LCD 表示を使ったファイラー・サンプル @n
			ST7565(R)、128 x 64 ピクセルの液晶を接続 @n
			/CS  ---> P53       (36) @n
			A0   ---> P50       (33) @n
			SD   ---> P13/SO20  (43) @n
			SCL  ---> P15/SCK20 (41) @n
			/RES ---> /RESET    ( 6)
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include "G13/system.hpp"
#include "common/port_utils.hpp"
#include "common/fifo.hpp"
#include "common/uart_io.hpp"
#include "common/itimer.hpp"
#include "common/format.hpp"
#include "common/delay.hpp"
#include "common/monograph.hpp"
#include "common/font6x12.hpp"
#include "common/kfont12.hpp"
#include "common/sdc_io.hpp"

// ターゲットＬＣＤのタイプを選択
#define LCD_ST7565
// #define LCD_SSD1306
#ifdef LCD_ST7565
#include "chip/ST7565.hpp"
#endif
#ifdef LCD_SSD1306
#include "chip/SSD1306.hpp"
#endif

namespace {
	// 送信、受信バッファの定義
	typedef utils::fifo<uint8_t, 32> buffer;
	// UART の定義（SAU02、SAU03）
	device::uart_io<device::SAU02, device::SAU03, buffer, buffer> uart_;

	device::itimer<uint8_t> itm_;

	// SDC CSI(SPI) の定義、CSI00 の通信では、「SAU00」を利用、０ユニット、チャネル０
	typedef device::csi_io<device::SAU00> csi;
	csi csi_;

	// FatFS インターフェースの定義
	typedef device::PORT<device::port_no::P0,  device::bitpos::B0> card_select;	///< カード選択信号
	typedef device::PORT<device::port_no::P0,  device::bitpos::B1> card_power;	///< カード電源制御
	typedef device::PORT<device::port_no::P14, device::bitpos::B6> card_detect;	///< カード検出

	utils::sdc_io<csi, card_select, card_power, card_detect> sdc_(csi_);

	// LCD CSI(SPI) の定義、CSI20 の通信では、「SAU10」を利用、１ユニット、チャネル０
	typedef device::csi_io<device::SAU10> csig;
	csig csig_;

	// LCD インターフェースの定義
	typedef device::PORT<device::port_no::P5,  device::bitpos::B5> lcd_sel;	///< LCD 選択信号
	typedef device::PORT<device::port_no::P5,  device::bitpos::B0> lcd_reg;	///< LCD レジスタ選択

#ifdef LCD_ST7565
	chip::ST7565<csig, lcd_sel, lcd_reg> lcd_(csig_);
#endif
#ifdef LCD_SSD1306
	chip::SSD1306<csig, lcd_sel, lcd_reg> lcd_(csig_);
#endif

	typedef graphics::font6x12 afont;
	typedef graphics::kfont12<16> kfont;
	kfont kfont_;
	graphics::monograph<128, 64, afont, kfont> bitmap_(kfont_);
}

const void* ivec_[] __attribute__ ((section (".ivec"))) = {
	/*  0 */  nullptr,
	/*  1 */  nullptr,
	/*  2 */  nullptr,
	/*  3 */  nullptr,
	/*  4 */  nullptr,
	/*  5 */  nullptr,
	/*  6 */  nullptr,
	/*  7 */  nullptr,
	/*  8 */  nullptr,
	/*  9 */  nullptr,
	/* 10 */  nullptr,
	/* 11 */  nullptr,
	/* 12 */  nullptr,
	/* 13 */  nullptr,
	/* 14 */  nullptr,
	/* 15 */  nullptr,
	/* 16 */  reinterpret_cast<void*>(uart_.send_task),
	/* 17 */  reinterpret_cast<void*>(uart_.recv_task),
	/* 18 */  reinterpret_cast<void*>(uart_.error_task),
	/* 19 */  nullptr,
	/* 20 */  nullptr,
	/* 21 */  nullptr,
	/* 22 */  nullptr,
	/* 23 */  nullptr,
	/* 24 */  nullptr,
	/* 25 */  nullptr,
	/* 26 */  reinterpret_cast<void*>(itm_.task),
};

extern "C" {
	void sci_putch(char ch)
	{
		uart_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		uart_.puts(str);
	}

	DSTATUS disk_initialize(BYTE drv) {
		return sdc_.at_mmc().disk_initialize(drv);
	}

	DSTATUS disk_status(BYTE drv) {
		return sdc_.at_mmc().disk_status(drv);
	}

	DRESULT disk_read(BYTE drv, BYTE* buff, DWORD sector, UINT count) {
		return sdc_.at_mmc().disk_read(drv, buff, sector, count);
	}

	DRESULT disk_write(BYTE drv, const BYTE* buff, DWORD sector, UINT count) {
		return sdc_.at_mmc().disk_write(drv, buff, sector, count);
	}

	DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void* buff) {
		return sdc_.at_mmc().disk_ioctl(drv, ctrl, buff);
	}

	DWORD get_fattime(void) {
#ifdef WITH_RTC
		time_t t = 0;
		if(!rtc_.get_time(t)) {
			utils::format("Stall RTC read (%d)\n") % static_cast<uint32_t>(iica_.get_last_error());
		}
		return utils::str::get_fattime(t);
#else
		return 0;
#endif
	}
};

int main(int argc, char* argv[])
{
	using namespace device;

	utils::port::pullup_all();  ///< 安全の為、全ての入力をプルアップ

	// インターバル・タイマー開始
	{
		uint8_t intr_level = 1;
		itm_.start(60, intr_level);
	}

	// UART 開始
	{
		uint8_t intr_level = 1;
		uart_.start(115200, intr_level);
	}

	// SD カードアクセス開始
	sdc_.initialize();

	// CSI graphics 開始
	{
		uint8_t intr_level = 0;
		if(!csig_.start(8000000, csig::PHASE::TYPE4, intr_level)) {
			uart_.puts("CSI Start fail...\n");
		}
	}

	uart_.puts("Start RL78/G13 SDC Filer sample\n");

	PM4.B3 = 0;  // output

	{
		lcd_.start(0x04, true);
		bitmap_.flash(0);
	}

	uint8_t n = 0;
	uint8_t nn = 0;

	while(1) {
		itm_.sync();

		sdc_.service();

		if(nn >= 3) {
			lcd_.copy(bitmap_.fb());
			bitmap_.flash(0);
			nn = 0;
		}
		++nn;

		bitmap_.draw_text(0, 0, "漢字");

		++n;
		if(n >= 30) n = 0;
		P4.B3 = n < 10 ? false : true;
	}
}
<commit_msg>update kanji text<commit_after>//=====================================================================//
/*!	@file
	@brief	LCD 表示を使ったファイラー・サンプル @n
			ST7565(R)、128 x 64 ピクセルの液晶を接続 @n
			/CS  ---> P53       (36) @n
			A0   ---> P50       (33) @n
			SD   ---> P13/SO20  (43) @n
			SCL  ---> P15/SCK20 (41) @n
			/RES ---> /RESET    ( 6)
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include "G13/system.hpp"
#include "common/port_utils.hpp"
#include "common/fifo.hpp"
#include "common/uart_io.hpp"
#include "common/itimer.hpp"
#include "common/format.hpp"
#include "common/delay.hpp"
#include "common/monograph.hpp"
#include "common/font6x12.hpp"
#include "common/kfont12.hpp"
#include "common/sdc_io.hpp"

// ターゲットＬＣＤのタイプを選択
#define LCD_ST7565
// #define LCD_SSD1306
#ifdef LCD_ST7565
#include "chip/ST7565.hpp"
#endif
#ifdef LCD_SSD1306
#include "chip/SSD1306.hpp"
#endif

namespace {
	// 送信、受信バッファの定義
	typedef utils::fifo<uint8_t, 32> buffer;
	// UART の定義（SAU02、SAU03）
	device::uart_io<device::SAU02, device::SAU03, buffer, buffer> uart_;

	device::itimer<uint8_t> itm_;

	// SDC CSI(SPI) の定義、CSI00 の通信では、「SAU00」を利用、０ユニット、チャネル０
	typedef device::csi_io<device::SAU00> csi;
	csi csi_;

	// FatFS インターフェースの定義
	typedef device::PORT<device::port_no::P0,  device::bitpos::B0> card_select;	///< カード選択信号
	typedef device::PORT<device::port_no::P0,  device::bitpos::B1> card_power;	///< カード電源制御
	typedef device::PORT<device::port_no::P14, device::bitpos::B6> card_detect;	///< カード検出

	utils::sdc_io<csi, card_select, card_power, card_detect> sdc_(csi_);

	// LCD CSI(SPI) の定義、CSI20 の通信では、「SAU10」を利用、１ユニット、チャネル０
	typedef device::csi_io<device::SAU10> csig;
	csig csig_;

	// LCD インターフェースの定義
	typedef device::PORT<device::port_no::P5,  device::bitpos::B5> lcd_sel;	///< LCD 選択信号
	typedef device::PORT<device::port_no::P5,  device::bitpos::B0> lcd_reg;	///< LCD レジスタ選択

#ifdef LCD_ST7565
	chip::ST7565<csig, lcd_sel, lcd_reg> lcd_(csig_);
#endif
#ifdef LCD_SSD1306
	chip::SSD1306<csig, lcd_sel, lcd_reg> lcd_(csig_);
#endif

	typedef graphics::font6x12 afont;
	typedef graphics::kfont12<16> kfont;
	kfont kfont_;
	graphics::monograph<128, 64, afont, kfont> bitmap_(kfont_);
}

const void* ivec_[] __attribute__ ((section (".ivec"))) = {
	/*  0 */  nullptr,
	/*  1 */  nullptr,
	/*  2 */  nullptr,
	/*  3 */  nullptr,
	/*  4 */  nullptr,
	/*  5 */  nullptr,
	/*  6 */  nullptr,
	/*  7 */  nullptr,
	/*  8 */  nullptr,
	/*  9 */  nullptr,
	/* 10 */  nullptr,
	/* 11 */  nullptr,
	/* 12 */  nullptr,
	/* 13 */  nullptr,
	/* 14 */  nullptr,
	/* 15 */  nullptr,
	/* 16 */  reinterpret_cast<void*>(uart_.send_task),
	/* 17 */  reinterpret_cast<void*>(uart_.recv_task),
	/* 18 */  reinterpret_cast<void*>(uart_.error_task),
	/* 19 */  nullptr,
	/* 20 */  nullptr,
	/* 21 */  nullptr,
	/* 22 */  nullptr,
	/* 23 */  nullptr,
	/* 24 */  nullptr,
	/* 25 */  nullptr,
	/* 26 */  reinterpret_cast<void*>(itm_.task),
};

extern "C" {
	void sci_putch(char ch)
	{
		uart_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		uart_.puts(str);
	}

	DSTATUS disk_initialize(BYTE drv) {
		return sdc_.at_mmc().disk_initialize(drv);
	}

	DSTATUS disk_status(BYTE drv) {
		return sdc_.at_mmc().disk_status(drv);
	}

	DRESULT disk_read(BYTE drv, BYTE* buff, DWORD sector, UINT count) {
		return sdc_.at_mmc().disk_read(drv, buff, sector, count);
	}

	DRESULT disk_write(BYTE drv, const BYTE* buff, DWORD sector, UINT count) {
		return sdc_.at_mmc().disk_write(drv, buff, sector, count);
	}

	DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void* buff) {
		return sdc_.at_mmc().disk_ioctl(drv, ctrl, buff);
	}

	DWORD get_fattime(void) {
#ifdef WITH_RTC
		time_t t = 0;
		if(!rtc_.get_time(t)) {
			utils::format("Stall RTC read (%d)\n") % static_cast<uint32_t>(iica_.get_last_error());
		}
		return utils::str::get_fattime(t);
#else
		return 0;
#endif
	}
};

int main(int argc, char* argv[])
{
	using namespace device;

	utils::port::pullup_all();  ///< 安全の為、全ての入力をプルアップ

	// インターバル・タイマー開始
	{
		uint8_t intr_level = 1;
		itm_.start(60, intr_level);
	}

	// UART 開始
	{
		uint8_t intr_level = 1;
		uart_.start(115200, intr_level);
	}

	// SD カードアクセス開始
	sdc_.initialize();

	// CSI graphics 開始
	{
		uint8_t intr_level = 0;
		if(!csig_.start(8000000, csig::PHASE::TYPE4, intr_level)) {
			uart_.puts("CSI Start fail...\n");
		}
	}

	uart_.puts("Start RL78/G13 SDC Filer sample\n");

	PM4.B3 = 0;  // output

	{
		lcd_.start(0x04, true);
		bitmap_.flash(0);
	}

	uint8_t n = 0;
	uint8_t nn = 0;

	while(1) {
		itm_.sync();

		bool f = sdc_.service();
		kfont_.set_mount(f);

		if(nn >= 3) {
			lcd_.copy(bitmap_.fb());
			bitmap_.flash(0);
			nn = 0;
		}
		++nn;

		bitmap_.draw_text(0, 0, "美しい漢字の表示");

		++n;
		if(n >= 30) n = 0;
		P4.B3 = n < 10 ? false : true;
	}
}
<|endoftext|>