1 /* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #ifndef XCOM_CACHE_H
24 #define XCOM_CACHE_H
25 
26 #include <stddef.h>
27 
28 #include "xcom/simset.h"
29 #include "xcom/xcom_profile.h"
30 #include "xdr_gen/xcom_vp.h"
31 
32 /*
33 We require that the number of elements in the cache is big enough enough that
34 it is always possible to find instances that are not busy.
35 Under normal circumstances the number of busy instances will be
36 less than event_horizon, since the proposers only considers
37 instances which belong to the local node.
38 A node may start proposing no_ops for instances belonging
39 to other nodes, meaning that event_horizon * NSERVERS instances may be
40 involved. However, for the time being, proposing a no_op for an instance
41 will not mark it as busy. This may change in the future, so a safe upper
42 limit on the number of nodes marked as busy is event_horizon * NSERVERS.
43 */
44 #define MIN_LENGTH MIN_CACHE_SIZE /* Also Default value */
45 #define INCREMENT MIN_LENGTH      /* Total number of slots to add/remove */
46 
47 #define is_cached(x) (hash_get(x) != NULL)
48 
49 struct lru_machine;
50 typedef struct lru_machine lru_machine;
51 
52 struct stack_machine;
53 typedef struct stack_machine stack_machine;
54 
55 struct pax_machine;
56 typedef struct pax_machine pax_machine;
57 
58 /* Definition of a Paxos instance */
59 struct pax_machine {
60   linkage hash_link;
61   stack_machine *stack_link;
62   lru_machine *lru;
63   synode_no synode;
64   double last_modified; /* Start time */
65   linkage rv; /* Tasks may sleep on this until something interesting happens */
66 
67   struct {
68     ballot bal;            /* The current ballot we are working on */
69     bit_set *prep_nodeset; /* Nodes which have answered my prepare */
70     ballot sent_prop;
71     bit_set *prop_nodeset; /* Nodes which have answered my propose */
72     pax_msg *msg;          /* The value we are trying to push */
73     ballot sent_learn;
74   } proposer;
75 
76   struct {
77     ballot promise; /* Promise to not accept any proposals less than this */
78     pax_msg *msg;   /* The value we have accepted */
79   } acceptor;
80 
81   struct {
82     pax_msg *msg; /* The value we have learned */
83   } learner;
84   int lock; /* Busy ? */
85   pax_op op;
86   int force_delivery;
87   int enforcer;
88 
89 #ifndef XCOM_STANDALONE
90   char is_instrumented;
91 #endif
92 };
93 
94 pax_machine *init_pax_machine(pax_machine *p, lru_machine *lru,
95                               synode_no synode);
96 int is_busy_machine(pax_machine *p);
97 int lock_pax_machine(pax_machine *p);
98 pax_machine *get_cache_no_touch(synode_no synode, bool_t force);
99 pax_machine *get_cache(synode_no synode);
100 pax_machine *force_get_cache(synode_no synode);
101 pax_machine *hash_get(synode_no synode);
102 char *dbg_machine_nodeset(pax_machine *p, u_int nodes);
103 char *dbg_pax_machine(pax_machine *p);
104 void init_cache();
105 void deinit_cache();
106 void unlock_pax_machine(pax_machine *p);
107 void xcom_cache_var_init();
108 size_t shrink_cache();
109 size_t pax_machine_size(pax_machine const *p);
110 synode_no cache_get_last_removed();
111 
112 void init_cache_size();
113 uint64_t add_cache_size(pax_machine *p);
114 uint64_t sub_cache_size(pax_machine *p);
115 int above_cache_limit();
116 uint64_t set_max_cache_size(uint64_t x);
117 int was_removed_from_cache(synode_no x);
118 uint16_t check_decrease();
119 void do_cache_maintenance();
120 
121 /* Unit testing */
122 #define DEC_THRESHOLD_LENGTH 500000 /* MIN_LENGTH * 10 */
123 #define MIN_TARGET_OCCUPATION 0.7F
124 #define DEC_THRESHOLD_SIZE 0.95F
125 #define MIN_LENGTH_THRESHOLD 0.9F
126 
127 uint64_t get_xcom_cache_occupation();
128 uint64_t get_xcom_cache_length();
129 uint64_t get_xcom_cache_size();
130 void set_length_increment(size_t increment);
131 void set_size_decrement(size_t decrement);
132 void set_dec_threshold_length(uint64_t threshold);
133 void set_min_target_occupation(float threshold);
134 void set_dec_threshold_size(float threshold);
135 void set_min_length_threshold(float threshold);
136 
137 #ifndef XCOM_STANDALONE
138 void psi_set_cache_resetting(int is_resetting);
139 void psi_report_cache_shutdown();
140 void psi_report_mem_free(size_t size, int is_instrumented);
141 int psi_report_mem_alloc(size_t size);
142 #else
143 #define psi_set_cache_resetting(x) \
144   do {                             \
145   } while (0)
146 #define psi_report_cache_shutdown() \
147   do {                              \
148   } while (0)
149 #define psi_report_mem_free(x) \
150   do {                         \
151   } while (0)
152 #define psi_report_mem_alloc(x) \
153   do {                          \
154   } while (0)
155 #endif
156 
157 enum {
158   CACHE_SHRINK_OK = 0,
159   CACHE_TOO_SMALL = 1,
160   CACHE_HASH_NOTEMPTY = 2,
161   CACHE_HIGH_OCCUPATION = 3,
162   CACHE_RESULT_LOW = 4,
163   CACHE_INCREASING = 5
164 };
165 
166 #endif
167