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