/*
 * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "precompiled.hpp"
#include "jfr/jfr.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/recorder/jfrRecorder.hpp"
#include "jfr/recorder/repository/jfrChunkWriter.hpp"
#include "jfr/recorder/repository/jfrEmergencyDump.hpp"
#include "jfr/recorder/repository/jfrRepository.hpp"
#include "jfr/recorder/service/jfrPostBox.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/mutex.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.inline.hpp"

static JfrRepository* _instance = NULL;

JfrRepository& JfrRepository::instance() {
  return *_instance;
}

static JfrChunkWriter* _chunkwriter = NULL;


JfrChunkWriter& JfrRepository::chunkwriter() {
  return *_chunkwriter;
}

JfrRepository::JfrRepository(JfrPostBox& post_box) : _path(NULL), _post_box(post_box) {}

bool JfrRepository::initialize() {
  assert(_chunkwriter == NULL, "invariant");
  _chunkwriter = new JfrChunkWriter();
  return _chunkwriter != NULL;
}

JfrRepository::~JfrRepository() {
  if (_path != NULL) {
    JfrCHeapObj::free(_path, strlen(_path) + 1);
    _path = NULL;
  }

  if (_chunkwriter != NULL) {
    delete _chunkwriter;
    _chunkwriter = NULL;
  }
}

JfrRepository* JfrRepository::create(JfrPostBox& post_box) {
  assert(_instance == NULL, "invariant");
  _instance = new JfrRepository(post_box);
  return _instance;
}

void JfrRepository::destroy() {
  assert(_instance != NULL, "invariant");
  delete _instance;
  _instance = NULL;
}

void JfrRepository::on_vm_error() {
  if (_path == NULL) {
    // completed already
    return;
  }
  JfrEmergencyDump::on_vm_error(_path);
}

bool JfrRepository::set_path(const char* path) {
  assert(path != NULL, "trying to set the repository path with a NULL string!");
  if (_path != NULL) {
    // delete existing
    JfrCHeapObj::free(_path, strlen(_path) + 1);
  }
  const size_t path_len = strlen(path);
  _path = JfrCHeapObj::new_array<char>(path_len + 1);
  if (_path == NULL) {
    return false;
  }
  strncpy(_path, path, path_len + 1);
  return true;
}

void JfrRepository::notify_on_new_chunk_path() {
  if (Jfr::is_recording()) {
    // rotations are synchronous, block until rotation completes
    instance()._post_box.post(MSG_ROTATE);
  }
}

void JfrRepository::set_chunk_path(const char* path) {
  chunkwriter().set_path(path);
}

jlong JfrRepository::current_chunk_start_nanos() {
  return chunkwriter().current_chunk_start_nanos();
}

/**
* Sets the file where data should be written.
*
* Recording  Previous  Current  Action
* ==============================================
*   true     null      null     Ignore, keep recording in-memory
*   true     null      file1    Start disk recording
*   true     file      null     Copy out metadata to disk and continue in-memory recording
*   true     file1     file2    Copy out metadata and start with new File (file2)
*   false     *        null     Ignore, but start recording to memory
*   false     *        file     Ignore, but start recording to disk
*/
void JfrRepository::set_chunk_path(jstring path, JavaThread* jt) {
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
  ResourceMark rm(jt);
  const char* const canonical_chunk_path = JfrJavaSupport::c_str(path, jt);
  if (NULL == canonical_chunk_path && !_chunkwriter->is_valid()) {
    // new output is NULL and current output is NULL
    return;
  }
  instance().set_chunk_path(canonical_chunk_path);
  notify_on_new_chunk_path();
}

void JfrRepository::set_path(jstring location, JavaThread* jt) {
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
  ResourceMark rm(jt);
  const char* const path = JfrJavaSupport::c_str(location, jt);
  if (path != NULL) {
    instance().set_path(path);
  }
}

bool JfrRepository::open_chunk(bool vm_error /* false */) {
  if (vm_error) {
    ResourceMark rm;
    _chunkwriter->set_path(JfrEmergencyDump::build_dump_path(_path));
  }
  return _chunkwriter->open();
}

size_t JfrRepository::close_chunk() {
  return _chunkwriter->close();
}

void JfrRepository::flush(JavaThread* jt) {
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
  if (!Jfr::is_recording()) {
    return;
  }
  if (!_chunkwriter->is_valid()) {
    return;
  }
  instance()._post_box.post(MSG_FLUSHPOINT);
}

size_t JfrRepository::flush_chunk() {
  return _chunkwriter->flush_chunk(true);
}
