1/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3#ident "$Id$"
4/*======
5This file is part of PerconaFT.
6
7
8Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9
10 PerconaFT is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License, version 2,
12 as published by the Free Software Foundation.
13
14 PerconaFT 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 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
21
22----------------------------------------
23
24 PerconaFT is free software: you can redistribute it and/or modify
25 it under the terms of the GNU Affero General Public License, version 3,
26 as published by the Free Software Foundation.
27
28 PerconaFT is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU Affero General Public License for more details.
32
33 You should have received a copy of the GNU Affero General Public License
34 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
35======= */
36
37#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38
39#include <string.h>
40
41#include <util/context.h>
42
43namespace toku {
44
45 static const context default_context(CTX_DEFAULT);
46 static __thread const context *tl_current_context = &default_context;
47
48 // save the old context, set the current context
49 context::context(const context_id id) :
50 m_old_ctx(tl_current_context),
51 m_id(id) {
52 tl_current_context = this;
53 }
54
55 // restore the old context
56 context::~context() {
57 tl_current_context = m_old_ctx;
58 }
59
60} // namespace toku
61
62// thread local context
63
64const toku::context *toku_thread_get_context() {
65 return toku::tl_current_context;
66}
67
68// engine status
69
70static struct context_status context_status;
71#define CONTEXT_STATUS_INIT(key, legend) TOKUFT_STATUS_INIT(context_status, key, nullptr, PARCOUNT, "context: " legend, TOKU_ENGINE_STATUS)
72
73void toku_context_status_init(void) {
74 CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_FULL_FETCH, "tree traversals blocked by a full fetch");
75 CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_PARTIAL_FETCH, "tree traversals blocked by a partial fetch");
76 CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_FULL_EVICTION, "tree traversals blocked by a full eviction");
77 CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_PARTIAL_EVICTION, "tree traversals blocked by a partial eviction");
78 CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_MESSAGE_INJECTION, "tree traversals blocked by a message injection");
79 CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_MESSAGE_APPLICATION, "tree traversals blocked by a message application");
80 CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_FLUSH, "tree traversals blocked by a flush");
81 CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_CLEANER, "tree traversals blocked by a the cleaner thread");
82 CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_OTHER, "tree traversals blocked by something uninstrumented");
83 CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_FULL_FETCH, "promotion blocked by a full fetch (should never happen)");
84 CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_PARTIAL_FETCH, "promotion blocked by a partial fetch (should never happen)");
85 CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_FULL_EVICTION, "promotion blocked by a full eviction (should never happen)");
86 CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_PARTIAL_EVICTION, "promotion blocked by a partial eviction (should never happen)");
87 CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_MESSAGE_INJECTION, "promotion blocked by a message injection");
88 CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_MESSAGE_APPLICATION, "promotion blocked by a message application");
89 CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_FLUSH, "promotion blocked by a flush");
90 CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_CLEANER, "promotion blocked by the cleaner thread");
91 CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_OTHER, "promotion blocked by something uninstrumented");
92 CONTEXT_STATUS_INIT(CTX_BLOCKED_OTHER, "something uninstrumented blocked by something uninstrumented");
93 context_status.initialized = true;
94}
95#undef FS_STATUS_INIT
96
97void toku_context_get_status(struct context_status *status) {
98 assert(context_status.initialized);
99 *status = context_status;
100}
101
102#define STATUS_INC(x, d) increment_partitioned_counter(context_status.status[x].value.parcount, d);
103
104void toku_context_note_frwlock_contention(const context_id blocked, const context_id blocking) {
105 assert(context_status.initialized);
106 if (blocked != CTX_SEARCH && blocked != CTX_PROMO) {
107 // Return early if this event is "unknown"
108 STATUS_INC(CTX_BLOCKED_OTHER, 1);
109 return;
110 }
111 switch (blocking) {
112 case CTX_FULL_FETCH:
113 if (blocked == CTX_SEARCH) {
114 STATUS_INC(CTX_SEARCH_BLOCKED_BY_FULL_FETCH, 1);
115 } else if (blocked == CTX_PROMO) {
116 STATUS_INC(CTX_PROMO_BLOCKED_BY_FULL_FETCH, 1);
117 }
118 break;
119 case CTX_PARTIAL_FETCH:
120 if (blocked == CTX_SEARCH) {
121 STATUS_INC(CTX_SEARCH_BLOCKED_BY_PARTIAL_FETCH, 1);
122 } else if (blocked == CTX_PROMO) {
123 STATUS_INC(CTX_PROMO_BLOCKED_BY_PARTIAL_FETCH, 1);
124 }
125 break;
126 case CTX_FULL_EVICTION:
127 if (blocked == CTX_SEARCH) {
128 STATUS_INC(CTX_SEARCH_BLOCKED_BY_FULL_EVICTION, 1);
129 } else if (blocked == CTX_PROMO) {
130 STATUS_INC(CTX_PROMO_BLOCKED_BY_FULL_EVICTION, 1);
131 }
132 break;
133 case CTX_PARTIAL_EVICTION:
134 if (blocked == CTX_SEARCH) {
135 STATUS_INC(CTX_SEARCH_BLOCKED_BY_PARTIAL_EVICTION, 1);
136 } else if (blocked == CTX_PROMO) {
137 STATUS_INC(CTX_PROMO_BLOCKED_BY_PARTIAL_EVICTION, 1);
138 }
139 break;
140 case CTX_MESSAGE_INJECTION:
141 if (blocked == CTX_SEARCH) {
142 STATUS_INC(CTX_SEARCH_BLOCKED_BY_MESSAGE_INJECTION, 1);
143 } else if (blocked == CTX_PROMO) {
144 STATUS_INC(CTX_PROMO_BLOCKED_BY_MESSAGE_INJECTION, 1);
145 }
146 break;
147 case CTX_MESSAGE_APPLICATION:
148 if (blocked == CTX_SEARCH) {
149 STATUS_INC(CTX_SEARCH_BLOCKED_BY_MESSAGE_APPLICATION, 1);
150 } else if (blocked == CTX_PROMO) {
151 STATUS_INC(CTX_PROMO_BLOCKED_BY_MESSAGE_APPLICATION, 1);
152 }
153 break;
154 case CTX_FLUSH:
155 if (blocked == CTX_SEARCH) {
156 STATUS_INC(CTX_SEARCH_BLOCKED_BY_FLUSH, 1);
157 } else if (blocked == CTX_PROMO) {
158 STATUS_INC(CTX_PROMO_BLOCKED_BY_FLUSH, 1);
159 }
160 break;
161 case CTX_CLEANER:
162 if (blocked == CTX_SEARCH) {
163 STATUS_INC(CTX_SEARCH_BLOCKED_BY_CLEANER, 1);
164 } else if (blocked == CTX_PROMO) {
165 STATUS_INC(CTX_PROMO_BLOCKED_BY_CLEANER, 1);
166 }
167 break;
168 default:
169 if (blocked == CTX_SEARCH) {
170 STATUS_INC(CTX_SEARCH_BLOCKED_OTHER, 1);
171 } else if (blocked == CTX_PROMO) {
172 STATUS_INC(CTX_PROMO_BLOCKED_OTHER, 1);
173 }
174 break;
175 }
176}
177
178void toku_context_status_destroy(void) {
179 for (int i = 0; i < CTX_STATUS_NUM_ROWS; ++i) {
180 if (context_status.status[i].type == PARCOUNT) {
181 destroy_partitioned_counter(context_status.status[i].value.parcount);
182 }
183 }
184}
185