// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 "kudu/master/location_cache.h"

#include <cstdio>
#include <mutex>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include <glog/logging.h>

#include "kudu/gutil/map-util.h"
#include "kudu/gutil/port.h"
#include "kudu/gutil/strings/charset.h"
#include "kudu/gutil/strings/split.h"
#include "kudu/gutil/strings/strip.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/util/stopwatch.h"
#include "kudu/util/subprocess.h"
#include "kudu/util/trace.h"

METRIC_DEFINE_counter(server, location_mapping_cache_hits,
                      "Location Mapping Cache Hits",
                      kudu::MetricUnit::kCacheHits,
                      "Number of times location mapping assignment used "
                      "cached data",
                      kudu::MetricLevel::kDebug);
METRIC_DEFINE_counter(server, location_mapping_cache_queries,
                      "Location Mapping Cache Queries",
                      kudu::MetricUnit::kCacheQueries,
                      "Number of queries to the location mapping cache",
                      kudu::MetricLevel::kDebug);

using std::string;
using std::vector;
using strings::Substitute;

namespace kudu {
namespace master {

namespace {
// Returns if 'location' is a valid location string, i.e. it begins with /
// and consists of /-separated tokens each of which contains only characters
// from the set [a-zA-Z0-9_-.].
bool IsValidLocation(const string& location) {
  if (location.empty() || location[0] != '/') {
    return false;
  }
  const strings::CharSet charset("abcdefghijklmnopqrstuvwxyz"
                                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                 "0123456789"
                                 "_-./");
  for (const auto c : location) {
    if (!charset.Test(c)) {
      return false;
    }
  }
  return true;
}
} // anonymous namespace

LocationCache::LocationCache(string location_mapping_cmd,
                             MetricEntity* metric_entity)
    : location_mapping_cmd_(std::move(location_mapping_cmd)) {
  if (metric_entity != nullptr) {
    location_mapping_cache_hits_ = metric_entity->FindOrCreateCounter(
          &METRIC_location_mapping_cache_hits);
    location_mapping_cache_queries_ = metric_entity->FindOrCreateCounter(
          &METRIC_location_mapping_cache_queries);
  }
}

Status LocationCache::GetLocation(const string& key, string* location) {
  if (PREDICT_TRUE(location_mapping_cache_queries_)) {
    location_mapping_cache_queries_->Increment();
  }
  {
    // First check whether the location for the key has already been assigned.
    shared_lock<rw_spinlock> l(location_map_lock_);
    const auto* value_ptr = FindOrNull(location_map_, key);
    if (value_ptr) {
      DCHECK(!value_ptr->empty());
      *location = *value_ptr;
      if (PREDICT_TRUE(location_mapping_cache_hits_)) {
        location_mapping_cache_hits_->Increment();
      }
      return Status::OK();
    }
  }
  string value;
  TRACE(Substitute("key $0: assigning location", key));
  Status s = GetLocationFromLocationMappingCmd(
      location_mapping_cmd_, key, &value);
  TRACE(Substitute("key $0: assigned location '$1'", key, value));
  if (s.ok()) {
    CHECK(!value.empty());
    std::lock_guard<rw_spinlock> l(location_map_lock_);
    // This simple implementation doesn't protect against multiple runs of the
    // location-mapping command for the same key.
    // TODO(KUDU-2771): queue concurrent requests for the same key
    InsertIfNotPresent(&location_map_, key, value);
    *location = value;
  }
  return s;
}

Status LocationCache::GetLocationFromLocationMappingCmd(const string& cmd,
                                                        const string& key,
                                                        string* location) {
  DCHECK(location);
  vector<string> argv = strings::Split(cmd, " ", strings::SkipEmpty());
  if (argv.empty()) {
    return Status::RuntimeError("invalid empty location mapping command");
  }
  argv.push_back(key);
  string stderr, location_temp;
  SCOPED_LOG_SLOW_EXECUTION(WARNING, 1000, "running location mapping command");
  Status s = Subprocess::Call(argv, /*stdin_in=*/"", &location_temp, &stderr);
  if (!s.ok()) {
    return Status::RuntimeError(
        Substitute("failed to run location mapping command: $0", s.ToString()),
        stderr);
  }
  StripWhiteSpace(&location_temp);
  // Special case an empty location for a better error.
  if (location_temp.empty()) {
    return Status::RuntimeError(
        "location mapping command returned invalid empty location");
  }
  if (!IsValidLocation(location_temp)) {
    return Status::RuntimeError(
        "location mapping command returned invalid location",
        location_temp);
  }
  *location = std::move(location_temp);
  return Status::OK();
}

} // namespace master
} // namespace kudu
