logMessageBuffer.hpp revision 11209:c84a6ce067ad
184865Sobrien/*
284865Sobrien * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
384865Sobrien * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
484865Sobrien *
584865Sobrien * This code is free software; you can redistribute it and/or modify it
684865Sobrien * under the terms of the GNU General Public License version 2 only, as
784865Sobrien * published by the Free Software Foundation.
884865Sobrien *
984865Sobrien * This code is distributed in the hope that it will be useful, but WITHOUT
1084865Sobrien * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1184865Sobrien * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1284865Sobrien * version 2 for more details (a copy is included in the LICENSE file that
1384865Sobrien * accompanied this code).
1484865Sobrien *
1584865Sobrien * You should have received a copy of the GNU General Public License version
1684865Sobrien * 2 along with this work; if not, write to the Free Software Foundation,
1784865Sobrien * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1884865Sobrien *
19218822Sdim * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20218822Sdim * or visit www.oracle.com if you need additional information or have any
2184865Sobrien * questions.
2284865Sobrien *
2384865Sobrien */
2484865Sobrien#ifndef SHARE_VM_LOGGING_LOGMESSAGEBUFFER_HPP
2584865Sobrien#define SHARE_VM_LOGGING_LOGMESSAGEBUFFER_HPP
2684865Sobrien
2784865Sobrien#include "logging/logDecorations.hpp"
2884865Sobrien#include "logging/logLevel.hpp"
2984865Sobrien#include "memory/allocation.hpp"
3084865Sobrien
3184865Sobrienclass LogMessageBuffer : public StackObj {
3284865Sobrien  friend class LogMessageTest;
3384865Sobrien protected:
3484865Sobrien  struct LogLine VALUE_OBJ_CLASS_SPEC {
3584865Sobrien    LogLevelType level;
3684865Sobrien    size_t message_offset;
3784865Sobrien  };
3884865Sobrien  static const size_t InitialLineCapacity = 10;
3984865Sobrien  static const size_t InitialMessageBufferCapacity = 1024;
4084865Sobrien
4184865Sobrien  size_t _message_buffer_size;
4284865Sobrien  size_t _message_buffer_capacity;
4384865Sobrien  char* _message_buffer;
4484865Sobrien
4584865Sobrien  size_t _line_count;
4684865Sobrien  size_t _line_capacity;
4784865Sobrien  LogLine* _lines;
4884865Sobrien
4984865Sobrien  bool _allocated;
5084865Sobrien  LogLevelType _least_detailed_level;
5184865Sobrien  size_t (*_prefix_fn)(char*, size_t);
5284865Sobrien
5384865Sobrien  void initialize_buffers();
5484865Sobrien
5584865Sobrien private:
5684865Sobrien  // Forbid copy assignment and copy constructor.
5784865Sobrien  void operator=(const LogMessageBuffer& ref) {}
5884865Sobrien  LogMessageBuffer(const LogMessageBuffer& ref) {}
5984865Sobrien
6084865Sobrien public:
6184865Sobrien  LogMessageBuffer();
6284865Sobrien  ~LogMessageBuffer();
6384865Sobrien
6484865Sobrien  class Iterator {
6584865Sobrien   private:
6684865Sobrien    const LogMessageBuffer& _message;
6784865Sobrien    size_t _current_line_index;
6884865Sobrien    LogLevelType _level;
6984865Sobrien    LogDecorations &_decorations;
7084865Sobrien
7184865Sobrien    void skip_messages_with_finer_level();
7284865Sobrien
7384865Sobrien   public:
7484865Sobrien    Iterator(const LogMessageBuffer& message, LogLevelType level, LogDecorations& decorations)
7584865Sobrien        : _message(message), _level(level), _decorations(decorations), _current_line_index(0) {
7684865Sobrien      skip_messages_with_finer_level();
7784865Sobrien    }
7884865Sobrien
7984865Sobrien    void operator++(int) {
8084865Sobrien      _current_line_index++;
8184865Sobrien      skip_messages_with_finer_level();
8284865Sobrien    }
8384865Sobrien
8484865Sobrien    bool is_at_end() {
8584865Sobrien      return _current_line_index == _message._line_count;
8684865Sobrien    }
8784865Sobrien
8884865Sobrien    const char* message() const {
8984865Sobrien      return _message._message_buffer + _message._lines[_current_line_index].message_offset;
9084865Sobrien    }
9184865Sobrien
9284865Sobrien    const LogDecorations& decorations() {
9384865Sobrien      _decorations.set_level(_message._lines[_current_line_index].level);
9484865Sobrien      return _decorations;
9584865Sobrien    }
9684865Sobrien  };
9784865Sobrien
9884865Sobrien  void reset();
9984865Sobrien
10084865Sobrien  LogLevelType least_detailed_level() const {
10184865Sobrien    return _least_detailed_level;
10284865Sobrien  }
10384865Sobrien
10484865Sobrien  Iterator iterator(LogLevelType level, LogDecorations& decorations) const {
10584865Sobrien    return Iterator(*this, level, decorations);
10684865Sobrien  }
10784865Sobrien
10884865Sobrien  // Lines in LogMessageBuffers are not automatically prefixed based on tags
10984865Sobrien  // like regular simple messages (see LogPrefix.hpp for more about prefixes).
11084865Sobrien  // It is, however, possible to specify a prefix per LogMessageBuffer,
11184865Sobrien  // using set_prefix(). Lines added to the LogMessageBuffer after a prefix
11284865Sobrien  // function has been set will be prefixed automatically.
11384865Sobrien  // Setting this to NULL will disable prefixing.
11484865Sobrien  void set_prefix(size_t (*prefix_fn)(char*, size_t)) {
11584865Sobrien    _prefix_fn = prefix_fn;
11684865Sobrien  }
11784865Sobrien
11884865Sobrien  ATTRIBUTE_PRINTF(3, 4)
11984865Sobrien  void write(LogLevelType level, const char* fmt, ...);
12084865Sobrien
12184865Sobrien  ATTRIBUTE_PRINTF(3, 0)
12284865Sobrien  virtual void vwrite(LogLevelType level, const char* fmt, va_list args);
12384865Sobrien
12484865Sobrien#define LOG_LEVEL(level, name) \
12584865Sobrien  LogMessageBuffer& v##name(const char* fmt, va_list args) ATTRIBUTE_PRINTF(2, 0); \
12684865Sobrien  LogMessageBuffer& name(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3);
12784865Sobrien  LOG_LEVEL_LIST
12884865Sobrien#undef LOG_LEVEL
12984865Sobrien};
13084865Sobrien
13184865Sobrien#endif // SHARE_VM_LOGGING_LOGMESSAGEBUFFER_HPP
13284865Sobrien