1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
5 Copyright (C) 2011-2012 Planets Communications B.V.
6 Copyright (C) 2013-2019 Bareos GmbH & Co. KG
7
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
11 in the file LICENSE.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA.
22 */
23
24 #include "lib/messages_resource.h"
25 #include "lib/message_destination_info.h"
26
27 #include <algorithm>
28 #include <iostream>
29
30 static pthread_mutex_t mutex_ = PTHREAD_MUTEX_INITIALIZER;
31
MessagesResource()32 MessagesResource::MessagesResource() : BareosResource(), send_msg_types_(3, 0)
33 {
34 return;
35 }
36
~MessagesResource()37 MessagesResource::~MessagesResource()
38 {
39 for (MessageDestinationInfo* d : dest_chain_) { delete d; }
40 }
41
Lock() const42 void MessagesResource::Lock() const { P(mutex_); }
43
Unlock() const44 void MessagesResource::Unlock() const { V(mutex_); }
45
WaitNotInUse() const46 void MessagesResource::WaitNotInUse() const
47 {
48 // leaves mutex_ locked
49 Lock();
50 while (in_use_ || closing_) {
51 Unlock();
52 Bmicrosleep(0, 200);
53 Lock();
54 }
55 }
56
ClearInUse()57 void MessagesResource::ClearInUse()
58 {
59 Lock();
60 in_use_ = false;
61 Unlock();
62 }
SetInUse()63 void MessagesResource::SetInUse()
64 {
65 WaitNotInUse();
66 in_use_ = true;
67 Unlock();
68 }
69
SetClosing()70 void MessagesResource::SetClosing() { closing_ = true; }
71
GetClosing() const72 bool MessagesResource::GetClosing() const { return closing_; }
73
ClearClosing()74 void MessagesResource::ClearClosing()
75 {
76 Lock();
77 closing_ = false;
78 Unlock();
79 }
80
IsClosing() const81 bool MessagesResource::IsClosing() const
82 {
83 Lock();
84 bool rtn = closing_;
85 Unlock();
86 return rtn;
87 }
88
DuplicateDestChain() const89 std::vector<MessageDestinationInfo*> MessagesResource::DuplicateDestChain()
90 const
91 {
92 std::vector<MessageDestinationInfo*> temp_chain;
93
94 for (MessageDestinationInfo* d : dest_chain_) {
95 MessageDestinationInfo* dnew = new MessageDestinationInfo(*d);
96 dnew->file_pointer_ = nullptr;
97 dnew->mail_filename_.clear();
98 temp_chain.push_back(dnew);
99 }
100
101 return temp_chain;
102 }
103
DuplicateResourceTo(MessagesResource & other) const104 void MessagesResource::DuplicateResourceTo(MessagesResource& other) const
105 {
106 other.dest_chain_ = DuplicateDestChain();
107 other.send_msg_types_ = send_msg_types_;
108 }
109
110 /*
111 * Called only during parsing of the config file.
112 *
113 * Note, where in the case of dest_code FILE is a filename,
114 * but in the case of MAIL is a space separated list of
115 * email addresses, ...
116 */
AddToExistingChain(MessageDestinationCode dest_code,int msg_type,const std::string & where)117 bool MessagesResource::AddToExistingChain(MessageDestinationCode dest_code,
118 int msg_type,
119 const std::string& where)
120 {
121 auto pos = std::find_if(dest_chain_.begin(), dest_chain_.end(),
122 [&dest_code](MessageDestinationInfo* d) {
123 return d->dest_code_ == dest_code;
124 });
125
126 if (pos != dest_chain_.end()) {
127 MessageDestinationInfo* d = *pos;
128 bool append = false;
129
130 if (where.empty() && d->where_.empty()) {
131 append = true;
132 } else if (where == d->where_) {
133 append = true;
134 }
135
136 if (append) {
137 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n", pos,
138 msg_type, dest_code, NSTDPRNT(where));
139 SetBit(msg_type, d->msg_types_);
140 SetBit(msg_type, send_msg_types_);
141 return true;
142 }
143 }
144 return false;
145 }
146
AddToNewChain(MessageDestinationCode dest_code,int msg_type,const std::string & where,const std::string & mail_cmd,const std::string & timestamp_format)147 void MessagesResource::AddToNewChain(MessageDestinationCode dest_code,
148 int msg_type,
149 const std::string& where,
150 const std::string& mail_cmd,
151 const std::string& timestamp_format)
152 {
153 MessageDestinationInfo* d;
154 d = new MessageDestinationInfo;
155 d->dest_code_ = dest_code;
156 SetBit(msg_type, d->msg_types_); /* Set type bit in structure */
157 SetBit(msg_type, send_msg_types_); /* Set type bit in our local */
158
159 d->where_ = where;
160 d->mail_cmd_ = mail_cmd;
161 d->timestamp_format_ = timestamp_format;
162
163 // insert in front for compatibility to the former alist implementation */
164 dest_chain_.insert(dest_chain_.begin(), d);
165
166 Dmsg6(850,
167 "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s "
168 "timestampformat=%s\n",
169 d, msg_type, dest_code, NSTDPRNT(where), NSTDPRNT(d->mail_cmd_),
170 NSTDPRNT(d->timestamp_format_));
171 }
172
AddMessageDestination(MessageDestinationCode dest_code,int msg_type,const std::string & where,const std::string & mail_cmd,const std::string & timestamp_format)173 void MessagesResource::AddMessageDestination(
174 MessageDestinationCode dest_code,
175 int msg_type,
176 const std::string& where,
177 const std::string& mail_cmd,
178 const std::string& timestamp_format)
179 {
180 if (!AddToExistingChain(dest_code, msg_type, where)) {
181 AddToNewChain(dest_code, msg_type, where, mail_cmd, timestamp_format);
182 }
183 }
184
185 /*
186 * Called only during parsing of the config file.
187 */
RemoveMessageDestination(MessageDestinationCode dest_code,int msg_type,const std::string & where)188 void MessagesResource::RemoveMessageDestination(
189 MessageDestinationCode dest_code,
190 int msg_type,
191 const std::string& where)
192 {
193 for (MessageDestinationInfo* d : dest_chain_) {
194 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NSTDPRNT(d->where_));
195 if (BitIsSet(msg_type, d->msg_types_) && (dest_code == d->dest_code_) &&
196 ((where.empty() && d->where_.empty()) || (where == d->where_))) {
197 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n", d, msg_type,
198 dest_code);
199 ClearBit(msg_type, d->msg_types_);
200 Dmsg0(850, "Return RemoveMessageDestination\n");
201 return;
202 }
203 }
204 }
205