1 /*
2  * Copyright (C) 2009-2018 Codership Oy <info@codership.com>
3  */
4 
5 #include "GCache.hpp"
6 
7 static const std::string GCACHE_PARAMS_DIR        ("gcache.dir");
8 static const std::string GCACHE_DEFAULT_DIR       ("");
9 static const std::string GCACHE_PARAMS_RB_NAME    ("gcache.name");
10 static const std::string GCACHE_DEFAULT_RB_NAME   ("galera.cache");
11 static const std::string GCACHE_PARAMS_MEM_SIZE   ("gcache.mem_size");
12 static const std::string GCACHE_DEFAULT_MEM_SIZE  ("0");
13 static const std::string GCACHE_PARAMS_RB_SIZE    ("gcache.size");
14 static const std::string GCACHE_DEFAULT_RB_SIZE   ("128M");
15 static const std::string GCACHE_PARAMS_PAGE_SIZE  ("gcache.page_size");
16 static const std::string GCACHE_DEFAULT_PAGE_SIZE (GCACHE_DEFAULT_RB_SIZE);
17 static const std::string GCACHE_PARAMS_KEEP_PAGES_SIZE("gcache.keep_pages_size");
18 static const std::string GCACHE_DEFAULT_KEEP_PAGES_SIZE("0");
19 #ifndef NDEBUG
20 static const std::string GCACHE_PARAMS_DEBUG      ("gcache.debug");
21 static const std::string GCACHE_DEFAULT_DEBUG     ("0");
22 #endif
23 static const std::string GCACHE_PARAMS_RECOVER    ("gcache.recover");
24 static const std::string GCACHE_DEFAULT_RECOVER   ("yes");
25 
26 const std::string&
27 gcache::GCache::PARAMS_DIR                 (GCACHE_PARAMS_DIR);
28 
29 void
register_params(gu::Config & cfg)30 gcache::GCache::Params::register_params(gu::Config& cfg)
31 {
32     cfg.add(GCACHE_PARAMS_DIR,             GCACHE_DEFAULT_DIR);
33     cfg.add(GCACHE_PARAMS_RB_NAME,         GCACHE_DEFAULT_RB_NAME);
34     cfg.add(GCACHE_PARAMS_MEM_SIZE,        GCACHE_DEFAULT_MEM_SIZE);
35     cfg.add(GCACHE_PARAMS_RB_SIZE,         GCACHE_DEFAULT_RB_SIZE);
36     cfg.add(GCACHE_PARAMS_PAGE_SIZE,       GCACHE_DEFAULT_PAGE_SIZE);
37     cfg.add(GCACHE_PARAMS_KEEP_PAGES_SIZE, GCACHE_DEFAULT_KEEP_PAGES_SIZE);
38 #ifndef NDEBUG
39     cfg.add(GCACHE_PARAMS_DEBUG,           GCACHE_DEFAULT_DEBUG);
40 #endif
41     cfg.add(GCACHE_PARAMS_RECOVER,         GCACHE_DEFAULT_RECOVER);
42 }
43 
44 static const std::string
name_value(gu::Config & cfg,const std::string & data_dir)45 name_value (gu::Config& cfg, const std::string& data_dir)
46 {
47     std::string dir(cfg.get(GCACHE_PARAMS_DIR));
48 
49     /* fallback to data_dir if gcache dir is not set */
50     if (GCACHE_DEFAULT_DIR == dir && !data_dir.empty())
51     {
52         dir = data_dir;
53         cfg.set (GCACHE_PARAMS_DIR, dir);
54     }
55 
56     std::string rb_name(cfg.get (GCACHE_PARAMS_RB_NAME));
57 
58     /* prepend directory name to RB file name if the former is not empty and
59      * the latter is not an absolute path */
60     if ('/' != rb_name[0] && !dir.empty())
61     {
62         rb_name = dir + '/' + rb_name;
63     }
64 
65     return rb_name;
66 }
67 
Params(gu::Config & cfg,const std::string & data_dir)68 gcache::GCache::Params::Params (gu::Config& cfg, const std::string& data_dir)
69     :
70     rb_name_  (name_value (cfg, data_dir)),
71     dir_name_ (cfg.get(GCACHE_PARAMS_DIR)),
72     mem_size_ (cfg.get<size_t>(GCACHE_PARAMS_MEM_SIZE)),
73     rb_size_  (cfg.get<size_t>(GCACHE_PARAMS_RB_SIZE)),
74     page_size_(cfg.get<size_t>(GCACHE_PARAMS_PAGE_SIZE)),
75     keep_pages_size_(cfg.get<size_t>(GCACHE_PARAMS_KEEP_PAGES_SIZE)),
76 #ifndef NDEBUG
77     debug_    (cfg.get<int>(GCACHE_PARAMS_DEBUG)),
78 #else
79     debug_    (0),
80 #endif
81     recover_  (cfg.get<bool>(GCACHE_PARAMS_RECOVER))
82 {}
83 
84 void
param_set(const std::string & key,const std::string & val)85 gcache::GCache::param_set (const std::string& key, const std::string& val)
86 {
87     if (key == GCACHE_PARAMS_RB_NAME)
88     {
89         gu_throw_error(EPERM) << "Can't change ring buffer name in runtime.";
90     }
91     else if (key == GCACHE_PARAMS_DIR)
92     {
93         gu_throw_error(EPERM) << "Can't change data dir in runtime.";
94     }
95     else if (key == GCACHE_PARAMS_MEM_SIZE)
96     {
97         size_t tmp_size = gu::Config::from_config<size_t>(val);
98 
99         gu::Lock lock(mtx);
100         /* locking here serves two purposes: ensures atomic setting of config
101          * and params.ram_size and syncs with malloc() method */
102 
103         config.set<size_t>(key, tmp_size);
104         params.mem_size(tmp_size);
105         mem.set_max_size(params.mem_size());
106     }
107     else if (key == GCACHE_PARAMS_RB_SIZE)
108     {
109         gu_throw_error(EPERM) << "Can't change ring buffer size in runtime.";
110     }
111     else if (key == GCACHE_PARAMS_PAGE_SIZE)
112     {
113         size_t tmp_size = gu::Config::from_config<size_t>(val);
114 
115         gu::Lock lock(mtx);
116         /* locking here serves two purposes: ensures atomic setting of config
117          * and params.ram_size and syncs with malloc() method */
118 
119         config.set<size_t>(key, tmp_size);
120         params.page_size(tmp_size);
121         ps.set_page_size(params.page_size());
122     }
123     else if (key == GCACHE_PARAMS_KEEP_PAGES_SIZE)
124     {
125         size_t tmp_size = gu::Config::from_config<size_t>(val);
126 
127         gu::Lock lock(mtx);
128         /* locking here serves two purposes: ensures atomic setting of config
129          * and params.ram_size and syncs with malloc() method */
130 
131         config.set<size_t>(key, tmp_size);
132         params.keep_pages_size(tmp_size);
133         ps.set_keep_size(params.keep_pages_size());
134     }
135     else if (key == GCACHE_PARAMS_RECOVER)
136     {
137         gu_throw_error(EINVAL) << "'" << key
138                                << "' has a meaning only on startup.";
139     }
140 #ifndef NDEBUG
141     else if (key == GCACHE_PARAMS_DEBUG)
142     {
143         int d = gu::Config::from_config<int>(val);
144 
145         gu::Lock lock(mtx);
146         /* locking here serves two purposes: ensures atomic setting of config
147          * and params.ram_size and syncs with malloc() method */
148 
149         config.set<int>(key, d);
150         params.debug(d);
151         mem.set_debug(params.debug());
152         rb.set_debug(params.debug());
153         ps.set_debug(params.debug());
154     }
155 #endif
156     else
157     {
158         throw gu::NotFound();
159     }
160 }
161