// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/log.h"

#include "vm/flags.h"
#include "vm/isolate.h"
#include "vm/thread.h"

namespace dart {

DEFINE_FLAG(bool, force_log_flush, false, "Always flush log messages.");

// The following flag is useful when debugging on Android, since
// adb logcat truncates messages that are "too long" (and always
// flushing would result in too many short messages).
DEFINE_FLAG(
    int,
    force_log_flush_at_size,
    0,
    "Flush log messages when buffer exceeds given size (disabled when 0).");

DEFINE_FLAG(charp,
            isolate_log_filter,
            NULL,
            "Log isolates whose name include the filter. "
            "Default: service isolate log messages are suppressed "
            "(specify 'vm-service' to log them).");

Log::Log(LogPrinter printer)
    : printer_(printer), manual_flush_(0), buffer_(0) {}

Log::~Log() {
  // Did someone enable manual flushing and then forgot to Flush?
  ASSERT(cursor() == 0);
}

Log* Log::Current() {
  Thread* thread = Thread::Current();
  if (thread == NULL) {
    OSThread* os_thread = OSThread::Current();
    ASSERT(os_thread != NULL);
    return os_thread->log();
  }
  Isolate* isolate = thread->isolate();
  if (isolate != NULL && Log::ShouldLogForIsolate(isolate)) {
    OSThread* os_thread = thread->os_thread();
    ASSERT(os_thread != NULL);
    return os_thread->log();
  } else {
    return Log::NoOpLog();
  }
}

void Log::Print(const char* format, ...) {
  if (this == NoOpLog()) {
    return;
  }

  va_list args;
  va_start(args, format);
  VPrint(format, args);
  va_end(args);
}

void Log::VPrint(const char* format, va_list args) {
  if (this == NoOpLog()) {
    return;
  }

  // Measure.
  va_list measure_args;
  va_copy(measure_args, args);
  intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
  va_end(measure_args);

  // Print.
  char* buffer = reinterpret_cast<char*>(malloc(len + 1));
  va_list print_args;
  va_copy(print_args, args);
  Utils::VSNPrint(buffer, (len + 1), format, print_args);
  va_end(print_args);

  // Append.
  // NOTE: does not append the '\0' character.
  for (intptr_t i = 0; i < len; i++) {
    buffer_.Add(buffer[i]);
  }
  free(buffer);

  if (ShouldFlush()) {
    Flush();
  }
}

void Log::Flush(const intptr_t cursor) {
  if (this == NoOpLog()) {
    return;
  }
  if (buffer_.is_empty()) {
    return;
  }
  if (buffer_.length() <= cursor) {
    return;
  }
  TerminateString();
  const char* str = &buffer_[cursor];
  ASSERT(str != NULL);
  printer_("%s", str);
  buffer_.TruncateTo(cursor);
}

void Log::Clear() {
  if (this == NoOpLog()) {
    return;
  }
  buffer_.TruncateTo(0);
}

intptr_t Log::cursor() const {
  return buffer_.length();
}

bool Log::ShouldLogForIsolate(const Isolate* isolate) {
  if (FLAG_isolate_log_filter == NULL) {
    if (isolate->is_service_isolate() || isolate->is_kernel_isolate()) {
      // By default, do not log for the service isolate.
      return false;
    }
    return true;
  }
  const char* name = isolate->name();
  ASSERT(name != NULL);
  if (strstr(name, FLAG_isolate_log_filter) == NULL) {
    // Filter does not match, do not log for this isolate.
    return false;
  }
  return true;
}

Log Log::noop_log_;
Log* Log::NoOpLog() {
  return &noop_log_;
}

void Log::TerminateString() {
  if (this == NoOpLog()) {
    return;
  }
  buffer_.Add('\0');
}

void Log::EnableManualFlush() {
  if (this == NoOpLog()) {
    return;
  }
  manual_flush_++;
}

void Log::DisableManualFlush(const intptr_t cursor) {
  if (this == NoOpLog()) {
    return;
  }

  manual_flush_--;
  ASSERT(manual_flush_ >= 0);
  if (manual_flush_ == 0) {
    Flush(cursor);
  }
}

bool Log::ShouldFlush() const {
  return ((manual_flush_ == 0) || FLAG_force_log_flush ||
          ((FLAG_force_log_flush_at_size > 0) &&
           (cursor() > FLAG_force_log_flush_at_size)));
}

void LogBlock::Initialize() {
  log_->EnableManualFlush();
}

LogBlock::~LogBlock() {
  log_->DisableManualFlush(cursor_);
}

}  // namespace dart
