1 /** @file
2
3 Record local definitions
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
23
24 #include "tscore/ink_platform.h"
25 #include "ConfigManager.h"
26 #include "tscore/ParseRules.h"
27 #include "P_RecCore.h"
28 #include "P_RecLocal.h"
29 #include "P_RecMessage.h"
30 #include "P_RecUtils.h"
31 #include "P_RecFile.h"
32 #include "LocalManager.h"
33 #include "FileManager.h"
34
35 // Marks whether the message handler has been initialized.
36 static bool message_initialized_p = false;
37
38 //-------------------------------------------------------------------------
39 // i_am_the_record_owner, only used for libreclocal.a
40 //-------------------------------------------------------------------------
41 bool
i_am_the_record_owner(RecT rec_type)42 i_am_the_record_owner(RecT rec_type)
43 {
44 switch (rec_type) {
45 case RECT_CONFIG:
46 case RECT_NODE:
47 case RECT_LOCAL:
48 return true;
49 case RECT_PROCESS:
50 case RECT_PLUGIN:
51 return false;
52 default:
53 ink_assert(!"Unexpected RecT type");
54 return false;
55 }
56 }
57
58 //-------------------------------------------------------------------------
59 // sync_thr
60 //-------------------------------------------------------------------------
61 static void *
sync_thr(void * data)62 sync_thr(void *data)
63 {
64 FileManager *configFiles = static_cast<FileManager *>(data);
65
66 while (true) {
67 RecBool check = true;
68
69 send_push_message();
70 RecSyncStatsFile();
71
72 // If we didn't successfully sync to disk, check whether we need to update ....
73 if (check) {
74 if (configFiles->isConfigStale()) {
75 RecSetRecordInt("proxy.node.config.reconfigure_required", 1, REC_SOURCE_DEFAULT);
76 }
77 }
78
79 usleep(REC_REMOTE_SYNC_INTERVAL_MS * 1000);
80 }
81
82 return nullptr;
83 }
84
85 //-------------------------------------------------------------------------
86 // config_update_thr
87 //-------------------------------------------------------------------------
88 static void *
config_update_thr(void *)89 config_update_thr(void * /* data */)
90 {
91 while (true) {
92 switch (RecExecConfigUpdateCbs(REC_LOCAL_UPDATE_REQUIRED)) {
93 case RECU_RESTART_TS:
94 RecSetRecordInt("proxy.node.config.restart_required.proxy", 1, REC_SOURCE_DEFAULT);
95 break;
96 case RECU_RESTART_TM:
97 RecSetRecordInt("proxy.node.config.restart_required.proxy", 1, REC_SOURCE_DEFAULT);
98 RecSetRecordInt("proxy.node.config.restart_required.manager", 1, REC_SOURCE_DEFAULT);
99 break;
100 case RECU_NULL:
101 case RECU_DYNAMIC:
102 break;
103 }
104
105 usleep(REC_CONFIG_UPDATE_INTERVAL_MS * 1000);
106 }
107 return nullptr;
108 }
109
110 //-------------------------------------------------------------------------
111 // RecMessageInit
112 //-------------------------------------------------------------------------
113 void
RecMessageInit()114 RecMessageInit()
115 {
116 ink_assert(g_mode_type != RECM_NULL);
117 lmgmt->registerMgmtCallback(MGMT_SIGNAL_LIBRECORDS, &RecMessageRecvThis);
118 message_initialized_p = true;
119 }
120
121 //-------------------------------------------------------------------------
122 // RecLocalInit
123 //-------------------------------------------------------------------------
124 int
RecLocalInit(Diags * _diags)125 RecLocalInit(Diags *_diags)
126 {
127 static bool initialized_p = false;
128 ;
129
130 if (initialized_p) {
131 return REC_ERR_OKAY;
132 }
133
134 g_mode_type = RECM_SERVER;
135
136 if (RecCoreInit(RECM_SERVER, _diags) == REC_ERR_FAIL) {
137 return REC_ERR_FAIL;
138 }
139
140 initialized_p = true;
141
142 return REC_ERR_OKAY;
143 }
144
145 //-------------------------------------------------------------------------
146 // RecLocalInitMessage
147 //-------------------------------------------------------------------------
148 int
RecLocalInitMessage()149 RecLocalInitMessage()
150 {
151 static bool initialized_p = false;
152
153 if (initialized_p) {
154 return REC_ERR_OKAY;
155 }
156
157 RecMessageInit();
158 if (RecMessageRegisterRecvCb(recv_message_cb, nullptr)) {
159 return REC_ERR_FAIL;
160 }
161
162 initialized_p = true;
163
164 return REC_ERR_OKAY;
165 }
166
167 //-------------------------------------------------------------------------
168 // RecLocalStart
169 //-------------------------------------------------------------------------
170 int
RecLocalStart(FileManager * configFiles)171 RecLocalStart(FileManager *configFiles)
172 {
173 ink_thread_create(nullptr, sync_thr, configFiles, 0, 0, nullptr);
174 ink_thread_create(nullptr, config_update_thr, nullptr, 0, 0, nullptr);
175 return REC_ERR_OKAY;
176 }
177
178 int
RecRegisterManagerCb(int id,RecManagerCb const & _fn)179 RecRegisterManagerCb(int id, RecManagerCb const &_fn)
180 {
181 return lmgmt->registerMgmtCallback(id, _fn);
182 }
183
184 void
RecSignalManager(int id,const char *,size_t)185 RecSignalManager(int id, const char *, size_t)
186 {
187 // Signals are messages sent across the management pipe, so by definition,
188 // you can't send a signal if you are a local process manager.
189 RecDebug(DL_Debug, "local manager dropping signal %d", id);
190 }
191
192 //-------------------------------------------------------------------------
193 // RecMessageSend
194 //-------------------------------------------------------------------------
195
196 int
RecMessageSend(RecMessage * msg)197 RecMessageSend(RecMessage *msg)
198 {
199 int msg_size;
200
201 if (!message_initialized_p) {
202 return REC_ERR_OKAY;
203 }
204
205 // Make a copy of the record, but truncate it to the size actually used
206 if (g_mode_type == RECM_CLIENT || g_mode_type == RECM_SERVER) {
207 msg->o_end = msg->o_write;
208 msg_size = sizeof(RecMessageHdr) + (msg->o_write - msg->o_start);
209 lmgmt->signalEvent(MGMT_EVENT_LIBRECORDS, reinterpret_cast<char *>(msg), msg_size);
210 }
211
212 return REC_ERR_OKAY;
213 }
214