// Copyright 2014 The Chromium OS 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 "metrics/serialization/serialization_utils.h"

#include <sys/file.h>

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "metrics/serialization/metric_sample.h"

#define READ_WRITE_ALL_FILE_FLAGS \
  (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)

namespace metrics {
namespace {

// Magic string that gets written at the beginning of the message file
// when the file has been partially uploaded.
constexpr char kMagicString[] = {'S', 'K', 'I', 'P'};

// Leaves a marker at the beginning of the metrics file, to indicate that the
// first part of the file has been processed.  The marker starts with a 4-byte
// magic number ("SKIP") followed by the offset to the remaining samples.
// Returns true on success, false on errors.
//
// Since the file could also start with a regular message, whose 4-byte header
// indicates its size, the magic number must be an invalid size i.e. greater
// than kMessageMaxLength when read as an uint32_t in any byte order.
bool RemovePreviousSamples(int fd) {
  off_t offset = lseek(fd, 0, SEEK_CUR);
  char marker[sizeof(kMagicString) + sizeof(off_t)];

  if (offset == static_cast<off_t>(-1)) {
    PLOG(ERROR) << "cannot find offset in metrics log";
    return false;
  } else if (offset < sizeof(marker)) {
    LOG(ERROR) << "metrics log offset is too small: " << offset;
    return false;
  }

  // Fill marker with magic string and offset, then store it.
  memcpy(marker, kMagicString, sizeof(kMagicString));
  memcpy(marker + sizeof(kMagicString), &offset, sizeof(off_t));
  if (pwrite(fd, marker, sizeof(marker), 0) != sizeof(marker)) {
    PLOG(ERROR) << "cannot write marker to metrics log";
    return false;
  }

  // Optimization: zero out file content between the marker and the first valid
  // sample.  NOTE: the fallocate() call writes zeros over the entire range
  // specified, and optimizes away zero-filled blocks.  We don't care if the
  // optimization fails.
  int punch_hole_mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
  if (fallocate(fd, punch_hole_mode, sizeof(marker), offset - sizeof(marker)))
    PLOG(WARNING) << "cannot punch hole in metrics log";

  return true;
}

// Seeks to the first valid sample in an incompletely-uploaded metrics log, as
// needed.
void SeekToSamples(int fd) {
  char marker[sizeof(kMagicString) + sizeof(off_t)];
  off_t offset;

  // Special case (and, we hope, also the most common): if the beginning of the
  // file does not contain a valid marker, nothing else needs to be done.
  // Also, we don't need to worry about errors, as we'll hit them again shortly.
  if (pread(fd, &marker, sizeof(marker), 0) != sizeof(marker) ||
      memcmp(marker, kMagicString, sizeof(kMagicString)) != 0)
    return;

  memcpy(&offset, marker + sizeof(kMagicString), sizeof(off_t));
  if (lseek(fd, offset, SEEK_SET) < 0) {
    // This isn't really recoverable, but the earlier pread() did not change
    // the offset, and an error will be generated when reading the first sample.
    PLOG(WARNING) << "could not seek to samples at offset " << offset;
  }
}

// Reads the next message from |file_descriptor| into |message|.
//
// |message| will be set to the empty string if no message could be read (EOF)
// or the message was badly constructed.
//
// Returns false if no message can be read from this file anymore (EOF or
// unrecoverable error).
bool ReadMessage(int fd, std::string* message_out, size_t* bytes_used_out) {
  CHECK(message_out);

  int result;
  uint32_t message_size;
  const size_t message_hdr_size = sizeof(message_size);
  // The file containing the metrics does not leave the device, so the writer
  // and the reader always have the same endianness.
  result = HANDLE_EINTR(read(fd, &message_size, sizeof(message_size)));
  if (result < 0) {
    PLOG(ERROR) << "failed to read message header";
    return false;
  }
  if (result == 0) {
    // This indicates a normal EOF.
    return false;
  }
  if (result < message_hdr_size) {
    LOG(ERROR) << "bad read size " << result << ", expecting "
               << sizeof(message_size);
    return false;
  }

  // kMessageMaxLength applies to the entire message: the 4-byte
  // length field and the content.
  if (message_size > SerializationUtils::kMessageMaxLength) {
    LOG(ERROR) << "message too long, length = " << message_size;
    if (HANDLE_EINTR(lseek(fd, message_size - message_hdr_size, SEEK_CUR)) ==
        -1) {
      PLOG(ERROR) << "error while skipping message. Aborting.";
      return false;
    }
    // Badly formatted message was skipped. Treat the badly formatted sample as
    // an empty sample.
    message_out->clear();
    return true;
  }

  if (message_size < message_hdr_size) {
    LOG(ERROR) << "message too short, length = " << message_size;
    return false;
  }

  message_size -= message_hdr_size;  // The message size includes itself.
  char buffer[SerializationUtils::kMessageMaxLength];
  if (!base::ReadFromFD(fd, buffer, message_size)) {
    LOG(ERROR) << "failed to read message body";
    return false;
  }
  *message_out = std::string(buffer, message_size);
  *bytes_used_out = message_size + message_hdr_size;
  return true;
}

}  // namespace

MetricSample SerializationUtils::ParseSample(const std::string& sample) {
  if (sample.empty())
    return MetricSample();

  // Can't split at \0 anymore, so replace null chars with \n.
  std::string sample_copy = sample;
  std::replace(sample_copy.begin(), sample_copy.end(), '\0', '\n');
  std::vector<std::string> parts = base::SplitString(
      sample_copy, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
  // We should have two null terminated strings so split should produce
  // three chunks.
  if (parts.size() != 3) {
    LOG(ERROR) << "splitting message on \\0 produced " << parts.size()
               << " parts (expected 3)";
    return MetricSample();
  }
  const std::string& name = parts[0];
  const std::string& value = parts[1];

  if (base::LowerCaseEqualsASCII(name, "crash")) {
    return MetricSample::CrashSample(value);
  } else if (base::LowerCaseEqualsASCII(name, "histogram")) {
    return MetricSample::ParseHistogram(value);
  } else if (base::LowerCaseEqualsASCII(name, "linearhistogram")) {
    return MetricSample::ParseLinearHistogram(value);
  } else if (base::LowerCaseEqualsASCII(name, "sparsehistogram")) {
    return MetricSample::ParseSparseHistogram(value);
  } else if (base::LowerCaseEqualsASCII(name, "useraction")) {
    return MetricSample::UserActionSample(value);
  } else {
    LOG(ERROR) << "invalid event type: " << name << ", value: " << value;
  }
  return MetricSample();
}

bool SerializationUtils::ReadAndTruncateMetricsFromFile(
    const std::string& filename,
    std::vector<MetricSample>* metrics,
    size_t sample_batch_max_length) {
  struct stat stat_buf;
  int result;
  off_t total_length = 0;

  result = stat(filename.c_str(), &stat_buf);
  if (result < 0) {
    if (errno != ENOENT)
      PLOG(ERROR) << filename << ": bad metrics file stat";

    // Nothing to collect---try later.
    return true;
  }
  if (stat_buf.st_size == 0) {
    // Also nothing to collect.
    return true;
  }
  base::ScopedFD fd(open(filename.c_str(), O_RDWR));
  if (fd.get() < 0) {
    PLOG(ERROR) << filename << ": cannot open";
    return true;
  }
  result = flock(fd.get(), LOCK_EX);
  if (result < 0) {
    PLOG(ERROR) << filename << ": cannot lock";
    return true;
  }

  // Skip consecutive zeros at the beginning of the file, which may have been
  // left by an earlier partial read if the file was too large.  Normally there
  // are none, but following long stretches of time without connectivity, there
  // could be a large number.  (They are optimized away by fallocate().)
  SeekToSamples(fd.get());

  // Try to process all messages in the log, but stop when
  // kMaxMetricsBytesCount has been exceeded.  If all messages are read and
  // processed, or an error occurs, truncate the file to zero size.  If the max
  // byte count is exceeded, stop processing samples, but set up the file to
  // continue at the next call.  There are races on daemon crash or system
  // crash: resolve them by allowing the loss of samples.
  bool skip_truncation = false;
  while (true) {
    std::string message;
    size_t bytes_used = 0;

    if (!ReadMessage(fd.get(), &message, &bytes_used))
      break;

    MetricSample sample = ParseSample(message);
    if (sample.IsValid())
      metrics->push_back(std::move(sample));

    total_length += bytes_used;
    if (total_length > sample_batch_max_length) {
      // Set up the file to continue processing.  Avoid final truncation,
      // unless there were errors.
      skip_truncation = RemovePreviousSamples(fd.get());
      break;
    }
  }

  if (!skip_truncation) {
    result = ftruncate(fd.get(), 0);
    if (result < 0)
      PLOG(ERROR) << "truncate metrics log";
  }

  result = flock(fd.get(), LOCK_UN);
  if (result < 0)
    PLOG(ERROR) << "unlock metrics log";

  return total_length <= sample_batch_max_length;
}

bool SerializationUtils::WriteMetricsToFile(
    const std::vector<MetricSample>& samples, const std::string& filename) {
  std::string output;
  for (const auto& sample : samples) {
    if (!sample.IsValid()) {
      return false;
    }
    std::string msg = sample.ToString();
    int32_t size = msg.length() + sizeof(int32_t);
    if (size > kMessageMaxLength) {
      LOG(ERROR) << "cannot write message: too long, length = " << size;
      return false;
    }
    output.append(reinterpret_cast<char*>(&size), sizeof(size));
    output.append(msg);
  }

  base::ScopedFD file_descriptor(open(filename.c_str(),
                                      O_WRONLY | O_APPEND | O_CREAT,
                                      READ_WRITE_ALL_FILE_FLAGS));

  if (file_descriptor.get() < 0) {
    PLOG(ERROR) << filename << ": cannot open";
    return false;
  }

  // Grab a lock to avoid chrome truncating the file underneath us. Keep the
  // file locked as briefly as possible. Freeing file_descriptor will close the
  // file and remove the lock.
  if (HANDLE_EINTR(flock(file_descriptor.get(), LOCK_EX)) < 0) {
    PLOG(ERROR) << filename << ": cannot lock";
    return false;
  }

  if (!base::WriteFileDescriptor(file_descriptor.get(), output.c_str(),
                                 output.size())) {
    PLOG(ERROR) << "error writing output";
    return false;
  }

  return true;
}

}  // namespace metrics
