/*
 * Copyright 2011 Google Inc.
 *
 * Licensed 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.
 */

// Author: fangfei@google.com (Fangfei Zhou)

#include "pagespeed/kernel/sharedmem/shared_circular_buffer.h"

#include <cstddef>

#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/abstract_shared_mem.h"
#include "pagespeed/kernel/base/circular_buffer.h"
#include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/writer.h"

namespace {
  const char kSharedCircularBufferObjName[] = "SharedCircularBuffer";
}    // namespace

namespace net_instaweb {

SharedCircularBuffer::SharedCircularBuffer(AbstractSharedMem* shm_runtime,
                                           const int buffer_capacity,
                                           const GoogleString& filename_prefix,
                                           const GoogleString& filename_suffix)
    : shm_runtime_(shm_runtime),
      buffer_capacity_(buffer_capacity),
      buffer_(NULL),
      filename_prefix_(filename_prefix),
      filename_suffix_(filename_suffix) {
}

SharedCircularBuffer::~SharedCircularBuffer() {
}

// Initialize shared mutex.
bool SharedCircularBuffer::InitMutex(MessageHandler* handler) {
  if (!segment_->InitializeSharedMutex(0, handler)) {
    handler->Message(
        kError, "Unable to create mutex for shared memory circular buffer");
    return false;
  }
  return true;
}

bool SharedCircularBuffer::InitSegment(bool parent,
                                       MessageHandler* handler) {
  // Size of segment includes mutex and circular buffer.
  int buffer_size = CircularBuffer::Sizeof(buffer_capacity_);
  size_t total = shm_runtime_->SharedMutexSize() + buffer_size;
  if (parent) {
    // In root process -> initialize the shared memory.
    segment_.reset(
        shm_runtime_->CreateSegment(SegmentName(), total, handler));
    if (segment_.get() == NULL) {
      return false;
    }
    // Initialize mutex.
    if (!InitMutex(handler)) {
      segment_.reset(NULL);
      shm_runtime_->DestroySegment(SegmentName(), handler);
      return false;
    }
  } else {
    // In child process -> attach to existing segment.
    segment_.reset(
        shm_runtime_->AttachToSegment(SegmentName(), total, handler));
    if (segment_.get() == NULL) {
      return false;
    }
  }
  // Attach Mutex.
  mutex_.reset(segment_->AttachToSharedMutex(0));
  // Initialize the circular buffer.
  int pos = shm_runtime_->SharedMutexSize();
  buffer_ = CircularBuffer::Init(
                parent,
                static_cast<void*>(const_cast<char*>(segment_->Base() + pos)),
                buffer_size, buffer_capacity_);
  return true;
}

void SharedCircularBuffer::Clear() {
  ScopedMutex hold_lock(mutex_.get());
  buffer_->Clear();
}

bool SharedCircularBuffer::Write(const StringPiece& message,
                                 MessageHandler* handler) {
  ScopedMutex hold_lock(mutex_.get());
  return buffer_->Write(message);
}

bool SharedCircularBuffer::Dump(Writer* writer, MessageHandler* handler) {
  ScopedMutex hold_lock(mutex_.get());
  return (writer->Write(buffer_->ToString(handler), handler));
}

GoogleString SharedCircularBuffer::ToString(MessageHandler* handler) {
  ScopedMutex hold_lock(mutex_.get());
  return buffer_->ToString(handler);
}

void SharedCircularBuffer::GlobalCleanup(MessageHandler* handler) {
  if (segment_.get() != NULL) {
    shm_runtime_->DestroySegment(SegmentName(), handler);
  }
}

GoogleString SharedCircularBuffer::SegmentName() const {
  return StrCat(filename_prefix_, kSharedCircularBufferObjName, ".",
                filename_suffix_);
}

}  // namespace net_instaweb
