Exemple #1
0
PoolFactory::PoolJson PoolFactory::parseNamedPool(folly::StringPiece name) {
  auto existingIt = pools_.find(name);
  if (existingIt == pools_.end()) {
    // get the pool from ConfigApi
    std::string jsonStr;
    checkLogic(configApi_.get(ConfigType::Pool, name.str(), jsonStr),
               "Can not read pool: {}", name);
    existingIt = pools_.emplace(
      name,
      std::make_pair(parseJsonString(jsonStr), PoolState::PARSED)
    ).first;
    return PoolJson(existingIt->first, existingIt->second.first);
  }

  name = existingIt->first;
  auto& json = existingIt->second.first;
  auto& state = existingIt->second.second;
  switch (state) {
    case PoolState::PARSED: return PoolJson(name, json);
    case PoolState::PARSING: throwLogic("Cycle in pool inheritance");
    case PoolState::NEW:
      state = PoolState::PARSING;
      break;
  }

  if (auto jInherit = json.get_ptr("inherit")) {
    checkLogic(jInherit->isString(),
               "Pool {}: inherit is not a string", name);
    auto& newJson = parseNamedPool(jInherit->stringPiece()).json;
    json.update_missing(newJson);
    json.erase("inherit");
  }
  state = PoolState::PARSED;
  return PoolJson(name, json);
}
Exemple #2
0
Entity* Parser::parseRight(const std::string & str, size_t & pos)
{
    Entity* value = 0;

    if ( str[ pos ] == '{' )
    {
        // next one is an object
        DEBUG("We read an object.")
        Object* obj = new Object;
        pos += 1;
        while( pos < str.size() && str[ pos ] != '}' )
        {
            parseLeft( str, pos, obj );
            ignoreChars( str, pos );
        }
        DEBUG("We just finished to read an object ! ")
        pos += 1; // we're on the }, go to the next char
        value = obj;
    }
    else if ( str[ pos ] == '"' )
    {
        // next one is a string
        DEBUG("We read a string")
        value = parseJsonString( str, pos );
    }
    else if ( str[ pos ] == '[' )
    {
        // next one is an array
        DEBUG("We read an array")
        Array* array = new Array;
        pos += 1;
        while( pos < str.size() && str[ pos ] != ']' )
        {
            Entity* child = parseRight( str, pos );
            if ( child )
                array->push_back( child );
        }
        DEBUG("We've finished to read our array.")
        pos += 1; // we're on the ], go to the next char
        value = array;
    }
    ignoreChars( str, pos );
    return value;
}
Exemple #3
0
std::shared_ptr<ClientPool>
PoolFactory::parsePool(const std::string& name, const folly::dynamic& json) {
  auto seenPoolIt = pools_.find(name);
  if (seenPoolIt != pools_.end()) {
    return seenPoolIt->second;
  }

  if (json.isString()) {
    // get the pool from ConfigApi
    std::string jsonStr;
    checkLogic(configApi_.get(ConfigType::Pool, name, jsonStr),
               "Can not read pool: {}", name);
    return parsePool(name, parseJsonString(jsonStr));
  } else {
    // one day we may add inheriting from local pool
    if (auto jinherit = json.get_ptr("inherit")) {
      checkLogic(jinherit->isString(),
                 "Pool {}: inherit is not a string", name);
      auto path = jinherit->stringPiece().str();
      std::string jsonStr;
      checkLogic(configApi_.get(ConfigType::Pool, path, jsonStr),
                 "Can not read pool from: {}", path);
      auto newJson = parseJsonString(jsonStr);
      for (auto& it : json.items()) {
        newJson.insert(it.first, it.second);
      }
      newJson.erase("inherit");
      return parsePool(name, newJson);
    }
  }

  // pool_locality
  std::chrono::milliseconds timeout{opts_.server_timeout_ms};
  if (auto jlocality = json.get_ptr("pool_locality")) {
    if (!jlocality->isString()) {
      MC_LOG_FAILURE(opts_, memcache::failure::Category::kInvalidConfig,
                     "Pool {}: pool_locality is not a string", name);
    } else {
      auto str = jlocality->stringPiece();
      if (str == "cluster") {
        if (opts_.cluster_pools_timeout_ms != 0) {
          timeout = std::chrono::milliseconds(opts_.cluster_pools_timeout_ms);
        }
      } else if (str == "region") {
        if (opts_.regional_pools_timeout_ms != 0) {
          timeout = std::chrono::milliseconds(opts_.regional_pools_timeout_ms);
        }
      } else {
        MC_LOG_FAILURE(opts_, memcache::failure::Category::kInvalidConfig,
                       "Pool {}: '{}' pool locality is not supported",
                       name, str);
      }
    }
  }

  // region & cluster
  std::string region, cluster;
  if (auto jregion = json.get_ptr("region")) {
    if (!jregion->isString()) {
      MC_LOG_FAILURE(opts_, memcache::failure::Category::kInvalidConfig,
                     "Pool {}: pool_region is not a string", name);
    } else {
      region = jregion->stringPiece().str();
    }
  }
  if (auto jcluster = json.get_ptr("cluster")) {
    if (!jcluster->isString()) {
      MC_LOG_FAILURE(opts_, memcache::failure::Category::kInvalidConfig,
                     "Pool {}: pool_cluster is not a string", name);
    } else {
      cluster = jcluster->stringPiece().str();
    }
  }

  if (auto jtimeout = json.get_ptr("server_timeout")) {
    if (!jtimeout->isInt()) {
      MC_LOG_FAILURE(opts_, memcache::failure::Category::kInvalidConfig,
                     "Pool {}: server_timeout is not an int", name);
    } else {
      timeout = std::chrono::milliseconds(jtimeout->getInt());
    }
  }

  if (!region.empty() && !cluster.empty()) {
    auto& route = opts_.default_route;
    if (region == route.getRegion() && cluster == route.getCluster()) {
      if (opts_.within_cluster_timeout_ms != 0) {
        timeout = std::chrono::milliseconds(opts_.within_cluster_timeout_ms);
      }
    } else if (region == route.getRegion()) {
      if (opts_.cross_cluster_timeout_ms != 0) {
        timeout = std::chrono::milliseconds(opts_.cross_cluster_timeout_ms);
      }
    } else {
      if (opts_.cross_region_timeout_ms != 0) {
        timeout = std::chrono::milliseconds(opts_.cross_region_timeout_ms);
      }
    }
  }

  auto protocol = parseProtocol(json, mc_ascii_protocol);

  bool keep_routing_prefix = false;
  if (auto jkeep_routing_prefix = json.get_ptr("keep_routing_prefix")) {
    checkLogic(jkeep_routing_prefix->isBool(),
               "Pool {}: keep_routing_prefix is not a bool");
    keep_routing_prefix = jkeep_routing_prefix->getBool();
  }

  uint64_t qosClass = opts_.default_qos_class;
  uint64_t qosPath = opts_.default_qos_path;
  if (auto jqos = json.get_ptr("qos")) {
    parseQos(folly::sformat("Pool {}", name), *jqos, qosClass, qosPath);
  }

  bool useSsl = false;
  if (auto juseSsl = json.get_ptr("use_ssl")) {
    checkLogic(juseSsl->isBool(), "Pool {}: use_ssl is not a bool", name);
    useSsl = juseSsl->getBool();
  }

  // servers
  auto jservers = json.get_ptr("servers");
  checkLogic(jservers, "Pool {}: servers not found", name);
  checkLogic(jservers->isArray(), "Pool {}: servers is not an array", name);
  auto clientPool = std::make_shared<ClientPool>(name);
  for (size_t i = 0; i < jservers->size(); ++i) {
    const auto& server = jservers->at(i);
    std::shared_ptr<AccessPoint> ap;
    bool serverUseSsl = useSsl;
    uint64_t serverQosClass = qosClass;
    uint64_t serverQosPath = qosPath;
    checkLogic(server.isString() || server.isObject(),
               "Pool {}: server #{} is not a string/object", name, i);
    if (server.isString()) {
      // we support both host:port and host:port:protocol
      ap = AccessPoint::create(server.stringPiece(), protocol);
      checkLogic(ap != nullptr,
                 "Pool {}: invalid server {}", name, server.stringPiece());
    } else { // object
      auto jhostname = server.get_ptr("hostname");
      checkLogic(jhostname,
                 "Pool {}: hostname not found for server #{}", name, i);
      checkLogic(jhostname->isString(),
                 "Pool {}: hostname is not a string for server #{}", name, i);

      if (auto jqos = server.get_ptr("qos")) {
        parseQos(folly::sformat("Pool {}, server #{}", name, i),
                 *jqos, qosClass, qosPath);
      }

      if (auto juseSsl = server.get_ptr("use_ssl")) {
        checkLogic(juseSsl->isBool(),
                   "Pool {}: use_ssl is not a bool for server #{}", name, i);
        serverUseSsl = juseSsl->getBool();
      }

      ap = AccessPoint::create(jhostname->stringPiece(),
                               parseProtocol(server, protocol));
      checkLogic(ap != nullptr, "Pool {}: invalid server #{}", name, i);
    }

    auto client = clientPool->emplaceClient(
      timeout,
      std::move(ap),
      keep_routing_prefix,
      serverUseSsl,
      serverQosClass,
      serverQosPath);

    clients_.push_back(std::move(client));
  } // servers

  // weights
  if (auto jweights = json.get_ptr("weights")) {
    clientPool->setWeights(*jweights);
  }

  pools_.emplace(name, clientPool);
  return clientPool;
}