1b2c13f5aSTrond Norbye/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2b2c13f5aSTrond Norbye#include <stdio.h>
3b2c13f5aSTrond Norbye#include <assert.h>
4b2c13f5aSTrond Norbye#include <iostream>
5b2c13f5aSTrond Norbye
6b2c13f5aSTrond Norbye#include <platform/dirutils.h>
7b2c13f5aSTrond Norbye#include <extensions/protocol_extension.h>
8b2c13f5aSTrond Norbye#include <memcached/config_parser.h>
9b2c13f5aSTrond Norbye
10b2c13f5aSTrond NorbyeEXTENSION_LOGGER_DESCRIPTOR *logger;
11b2c13f5aSTrond Norbye
12b2c13f5aSTrond Norbyeextern "C" {
13b2c13f5aSTrond Norbye    static EXTENSION_LOG_LEVEL get_log_level(void);
14b2c13f5aSTrond Norbye    static bool register_extension(extension_type_t type, void *extension);
15b2c13f5aSTrond Norbye    static void register_callback(ENGINE_HANDLE *eh,
16b2c13f5aSTrond Norbye                                  ENGINE_EVENT_TYPE type,
17b2c13f5aSTrond Norbye                                  EVENT_CALLBACK cb,
18b2c13f5aSTrond Norbye                                  const void *cb_data);
19b2c13f5aSTrond Norbye    static SERVER_HANDLE_V1 *get_server_api(void);
20b2c13f5aSTrond Norbye}
21b2c13f5aSTrond Norbye
22b2c13f5aSTrond Norbye
23b2c13f5aSTrond Norbyestatic EXTENSION_LOG_LEVEL get_log_level(void)
24b2c13f5aSTrond Norbye{
25b2c13f5aSTrond Norbye    return EXTENSION_LOG_DETAIL;
26b2c13f5aSTrond Norbye}
27b2c13f5aSTrond Norbye
28b2c13f5aSTrond Norbyestatic bool register_extension(extension_type_t type, void *extension)
29b2c13f5aSTrond Norbye{
30b2c13f5aSTrond Norbye    assert(type == EXTENSION_LOGGER);
31b2c13f5aSTrond Norbye    logger = reinterpret_cast<EXTENSION_LOGGER_DESCRIPTOR *>(extension);
32b2c13f5aSTrond Norbye    return true;
33b2c13f5aSTrond Norbye}
34b2c13f5aSTrond Norbye
35b2c13f5aSTrond Norbyestatic void register_callback(ENGINE_HANDLE *eh,
36b2c13f5aSTrond Norbye                              ENGINE_EVENT_TYPE type,
37b2c13f5aSTrond Norbye                              EVENT_CALLBACK cb,
38b2c13f5aSTrond Norbye                              const void *cb_data)
39b2c13f5aSTrond Norbye{
40b2c13f5aSTrond Norbye    (void)eh;
41b2c13f5aSTrond Norbye    (void)type;
42b2c13f5aSTrond Norbye    (void)cb;
43b2c13f5aSTrond Norbye    (void)cb_data;
44b2c13f5aSTrond Norbye}
45b2c13f5aSTrond Norbye
46b2c13f5aSTrond Norbyestatic SERVER_HANDLE_V1 *get_server_api(void)
47b2c13f5aSTrond Norbye{
48b2c13f5aSTrond Norbye    static int init;
49b2c13f5aSTrond Norbye    static SERVER_CORE_API core_api;
50b2c13f5aSTrond Norbye    static SERVER_COOKIE_API server_cookie_api;
51b2c13f5aSTrond Norbye    static SERVER_STAT_API server_stat_api;
52b2c13f5aSTrond Norbye    static SERVER_LOG_API server_log_api;
53b2c13f5aSTrond Norbye    static SERVER_EXTENSION_API extension_api;
54b2c13f5aSTrond Norbye    static SERVER_CALLBACK_API callback_api;
55b2c13f5aSTrond Norbye    static ALLOCATOR_HOOKS_API hooks_api;
56b2c13f5aSTrond Norbye    static SERVER_HANDLE_V1 rv;
57b2c13f5aSTrond Norbye
58b2c13f5aSTrond Norbye    if (!init) {
59b2c13f5aSTrond Norbye        init = 1;
60b2c13f5aSTrond Norbye
61b2c13f5aSTrond Norbye        core_api.parse_config = parse_config;
62b2c13f5aSTrond Norbye        server_log_api.get_level = get_log_level;
63b2c13f5aSTrond Norbye        extension_api.register_extension = register_extension;
64b2c13f5aSTrond Norbye        callback_api.register_callback = register_callback;
65b2c13f5aSTrond Norbye
66b2c13f5aSTrond Norbye        rv.interface = 1;
67b2c13f5aSTrond Norbye        rv.core = &core_api;
68b2c13f5aSTrond Norbye        rv.stat = &server_stat_api;
69b2c13f5aSTrond Norbye        rv.extension = &extension_api;
70b2c13f5aSTrond Norbye        rv.callback = &callback_api;
71b2c13f5aSTrond Norbye        rv.log = &server_log_api;
72b2c13f5aSTrond Norbye        rv.cookie = &server_cookie_api;
73b2c13f5aSTrond Norbye        rv.alloc_hooks = &hooks_api;
74b2c13f5aSTrond Norbye    }
75b2c13f5aSTrond Norbye
76b2c13f5aSTrond Norbye    return &rv;
77b2c13f5aSTrond Norbye}
78b2c13f5aSTrond Norbye
79b2c13f5aSTrond Norbyestatic void remove_files(std::vector<std::string> &files) {
80b2c13f5aSTrond Norbye    for (std::vector<std::string>::iterator iter = files.begin();
81b2c13f5aSTrond Norbye         iter != files.end();
82b2c13f5aSTrond Norbye         ++iter) {
83b2c13f5aSTrond Norbye        CouchbaseDirectoryUtilities::rmrf(*iter);
84b2c13f5aSTrond Norbye    }
85b2c13f5aSTrond Norbye}
86b2c13f5aSTrond Norbye
87b2c13f5aSTrond Norbyeint main(int argc, char **argv)
88b2c13f5aSTrond Norbye{
89b2c13f5aSTrond Norbye    EXTENSION_ERROR_CODE ret;
90b2c13f5aSTrond Norbye    int ii;
91b2c13f5aSTrond Norbye
92b2c13f5aSTrond Norbye    std::vector<std::string> files;
93b2c13f5aSTrond Norbye    files = CouchbaseDirectoryUtilities::findFilesWithPrefix("log_test");
94b2c13f5aSTrond Norbye    if (!files.empty()) {
95b2c13f5aSTrond Norbye        remove_files(files);
96b2c13f5aSTrond Norbye    }
97b2c13f5aSTrond Norbye
98b2c13f5aSTrond Norbye
99835f0308SDave Rigby    // Note: Ensure buffer is at least 4* larger than the expected message
100835f0308SDave Rigby    // length, otherwise the writer will be blocked waiting for the flusher
101835f0308SDave Rigby    // thread to timeout and write (as we haven't actually hit the 75%
102835f0308SDave Rigby    // watermark which would normally trigger an immediate flush).
103835f0308SDave Rigby    ret = memcached_extensions_initialize("unit_test=true;prettyprint=true;loglevel=warning;cyclesize=1024;buffersize=512;sleeptime=1;filename=log_test", get_server_api);
104b2c13f5aSTrond Norbye    assert(ret == EXTENSION_SUCCESS);
105b2c13f5aSTrond Norbye
106835f0308SDave Rigby    for (ii = 0; ii < 8192; ++ii) {
107b2c13f5aSTrond Norbye        logger->log(EXTENSION_LOG_DETAIL, NULL,
108b2c13f5aSTrond Norbye                    "Hei hopp, dette er bare noe tull... Paa tide med kaffe!!");
109b2c13f5aSTrond Norbye    }
110b2c13f5aSTrond Norbye
111b2c13f5aSTrond Norbye    logger->shutdown();
112b2c13f5aSTrond Norbye
113b2c13f5aSTrond Norbye    files = CouchbaseDirectoryUtilities::findFilesWithPrefix("log_test");
114b2c13f5aSTrond Norbye
115b2c13f5aSTrond Norbye    // The cyclesize isn't a hard limit. We don't truncate entries that
116b2c13f5aSTrond Norbye    // won't fit to move to the next file. We'll rather dump the entire
117b2c13f5aSTrond Norbye    // buffer to the file. This means that each file may in theory be
118b2c13f5aSTrond Norbye    // up to a buffersize bigger than the cyclesize.. It is a bit hard
119b2c13f5aSTrond Norbye    // determine the exact number of files we should get here.. Testing
120b2c13f5aSTrond Norbye    // on MacOSX I'm logging 97 bytes in my timezone (summertime), but
121b2c13f5aSTrond Norbye    // on Windows it turned out to be a much longer timezone name etc..
122b2c13f5aSTrond Norbye    // I'm assuming that we should end up with 90+ files..
123b2c13f5aSTrond Norbye    assert(files.size() >= 90);
124b2c13f5aSTrond Norbye    remove_files(files);
125b2c13f5aSTrond Norbye
126b2c13f5aSTrond Norbye    return 0;
127b2c13f5aSTrond Norbye}
128