/*
 * Dynomite - A thin, distributed replication layer for multi non-distributed
 * storages. Copyright (C) 2014 Netflix, Inc.
 */

/*
 * twemproxy - A fast and lightweight proxy for memcached protocol.
 * Copyright (C) 2011 Twitter, 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.
 */

#ifndef _DYN_LOG_H_
#define _DYN_LOG_H_

struct logger {
  char *name; /* log file name */
  int level;  /* log level */
  int fd;     /* log file descriptor */
  int nerror; /* # log error */
};

#define LOG_EMERG 0   /* system in unusable */
#define LOG_ALERT 1   /* action must be taken immediately */
#define LOG_CRIT 2    /* critical conditions */
#define LOG_ERR 3     /* error conditions */
#define LOG_WARN 4    /* warning conditions */
#define LOG_NOTICE 5  /* normal but significant condition (default) */
#define LOG_INFO 6    /* informational */
#define LOG_DEBUG 7   /* debug messages */
#define LOG_VERB 8    /* verbose messages */
#define LOG_VVERB 9   /* verbose messages on crack */
#define LOG_VVVERB 10 /* verbose messages on ganga */
#define LOG_PVERB 11  /* periodic verbose messages on crack */

#define LOG_MAX_LEN 512 /* max length of log message */

/*
 * log_stderr   - log to stderr
 * loga         - log always
 * loga_hexdump - log hexdump always
 * log_error    - error log messages
 * log_warn     - warning log messages
 * log_panic    - log messages followed by a panic
 * ...
 * log_debug    - debug log messages based on a log level
 * log_hexdump  - hexadump -C of a log buffer
 */
#ifdef DN_DEBUG_LOG

#define log_debug(_level, ...)                      \
  do {                                              \
    if (log_loggable(_level) != 0) {                \
      _log(__FUNCTION__, __LINE__, 0, __VA_ARGS__); \
    }                                               \
  } while (0)

#define log_hexdump(_level, _data, _datalen, ...)                            \
  do {                                                                       \
    if (log_loggable(_level) != 0) {                                         \
      _log(__FUNCTION__, __LINE__, 0, __VA_ARGS__);                          \
      _log_hexdump(__FUNCTION__, __LINE__, (char *)(_data), (int)(_datalen), \
                   __VA_ARGS__);                                             \
    }                                                                        \
  } while (0)

#else

#define log_debug(_level, ...)
#define log_hexdump(_level, _data, _datalen, ...)

#endif

#define log_notice(...) log_debug(LOG_NOTICE, __VA_ARGS__);
#define log_info(...) log_debug(LOG_INFO, __VA_ARGS__);

#define log_stderr(...)       \
  do {                        \
    _log_stderr(__VA_ARGS__); \
  } while (0)

#define loga(...)                                 \
  do {                                            \
    _log(__FUNCTION__, __LINE__, 0, __VA_ARGS__); \
  } while (0)

#define loga_hexdump(_data, _datalen, ...)                                 \
  do {                                                                     \
    _log(__FUNCTION__, __LINE__, 0, __VA_ARGS__);                          \
    _log_hexdump(__FUNCTION__, __LINE__, (char *)(_data), (int)(_datalen), \
                 __VA_ARGS__);                                             \
  } while (0)

#define log_error(...)                              \
  do {                                              \
    if (log_loggable(LOG_ALERT) != 0) {             \
      _log(__FUNCTION__, __LINE__, 0, __VA_ARGS__); \
    }                                               \
  } while (0)

#define log_warn(...)                               \
  do {                                              \
    if (log_loggable(LOG_WARN) != 0) {              \
      _log(__FUNCTION__, __LINE__, 0, __VA_ARGS__); \
    }                                               \
  } while (0)

#define log_panic(...)                              \
  do {                                              \
    if (log_loggable(LOG_EMERG) != 0) {             \
      _log(__FUNCTION__, __LINE__, 1, __VA_ARGS__); \
    }                                               \
  } while (0)

int log_init(int level, char *filename);
void log_deinit(void);
void log_level_up(void);
void log_level_down(void);
void log_level_set(int level);
void log_reopen(void);
int log_loggable(int level);
void _log(const char *file, int line, int panic, const char *fmt, ...);
void _log_stderr(const char *fmt, ...);
void _log_hexdump(const char *file, int line, char *data, int datalen,
                  const char *fmt, ...);

#endif
