1 /* Copyright (c) 2010, 2021, Oracle and/or its affiliates.
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 Street, Fifth Floor, Boston, MA 02110-1301, USA */
22
23 /**
24 @file storage/perfschema/pfs_account.cc
25 Performance schema account (implementation).
26 */
27
28 #include "my_global.h"
29 #include "my_sys.h"
30 #include "pfs.h"
31 #include "pfs_stat.h"
32 #include "pfs_instr.h"
33 #include "pfs_setup_actor.h"
34 #include "pfs_host.h"
35 #include "pfs_host.h"
36 #include "pfs_user.h"
37 #include "pfs_account.h"
38 #include "pfs_global.h"
39 #include "pfs_instr_class.h"
40 #include "pfs_buffer_container.h"
41
42 /**
43 @addtogroup Performance_schema_buffers
44 @{
45 */
46
47 LF_HASH account_hash;
48 static bool account_hash_inited= false;
49
50 /**
51 Initialize the user buffers.
52 @param param sizing parameters
53 @return 0 on success
54 */
init_account(const PFS_global_param * param)55 int init_account(const PFS_global_param *param)
56 {
57 if (global_account_container.init(param->m_account_sizing))
58 return 1;
59
60 return 0;
61 }
62
63 /** Cleanup all the account buffers. */
cleanup_account(void)64 void cleanup_account(void)
65 {
66 global_account_container.cleanup();
67 }
68
69 C_MODE_START
account_hash_get_key(const uchar * entry,size_t * length,my_bool)70 static uchar *account_hash_get_key(const uchar *entry, size_t *length,
71 my_bool)
72 {
73 const PFS_account * const *typed_entry;
74 const PFS_account *account;
75 const void *result;
76 typed_entry= reinterpret_cast<const PFS_account* const *> (entry);
77 assert(typed_entry != NULL);
78 account= *typed_entry;
79 assert(account != NULL);
80 *length= account->m_key.m_key_length;
81 result= account->m_key.m_hash_key;
82 return const_cast<uchar*> (reinterpret_cast<const uchar*> (result));
83 }
84 C_MODE_END
85
86 /**
87 Initialize the user hash.
88 @return 0 on success
89 */
init_account_hash(const PFS_global_param * param)90 int init_account_hash(const PFS_global_param *param)
91 {
92 if ((! account_hash_inited) && (param->m_account_sizing != 0))
93 {
94 lf_hash_init(&account_hash, sizeof(PFS_account*), LF_HASH_UNIQUE,
95 0, 0, account_hash_get_key, &my_charset_bin);
96 account_hash_inited= true;
97 }
98 return 0;
99 }
100
101 /** Cleanup the user hash. */
cleanup_account_hash(void)102 void cleanup_account_hash(void)
103 {
104 if (account_hash_inited)
105 {
106 lf_hash_destroy(&account_hash);
107 account_hash_inited= false;
108 }
109 }
110
get_account_hash_pins(PFS_thread * thread)111 static LF_PINS* get_account_hash_pins(PFS_thread *thread)
112 {
113 if (unlikely(thread->m_account_hash_pins == NULL))
114 {
115 if (! account_hash_inited)
116 return NULL;
117 thread->m_account_hash_pins= lf_hash_get_pins(&account_hash);
118 }
119 return thread->m_account_hash_pins;
120 }
121
set_account_key(PFS_account_key * key,const char * user,uint user_length,const char * host,uint host_length)122 static void set_account_key(PFS_account_key *key,
123 const char *user, uint user_length,
124 const char *host, uint host_length)
125 {
126 assert(user_length <= USERNAME_LENGTH);
127 assert(host_length <= HOSTNAME_LENGTH);
128
129 char *ptr= &key->m_hash_key[0];
130 if (user_length > 0)
131 {
132 memcpy(ptr, user, user_length);
133 ptr+= user_length;
134 }
135 ptr[0]= 0;
136 ptr++;
137 if (host_length > 0)
138 {
139 memcpy(ptr, host, host_length);
140 ptr+= host_length;
141 }
142 ptr[0]= 0;
143 ptr++;
144 key->m_key_length= ptr - &key->m_hash_key[0];
145 }
146
147 PFS_account *
find_or_create_account(PFS_thread * thread,const char * username,uint username_length,const char * hostname,uint hostname_length)148 find_or_create_account(PFS_thread *thread,
149 const char *username, uint username_length,
150 const char *hostname, uint hostname_length)
151 {
152 LF_PINS *pins= get_account_hash_pins(thread);
153 if (unlikely(pins == NULL))
154 {
155 global_account_container.m_lost++;
156 return NULL;
157 }
158
159 PFS_account_key key;
160 set_account_key(&key, username, username_length,
161 hostname, hostname_length);
162
163 PFS_account **entry;
164 PFS_account *pfs;
165 uint retry_count= 0;
166 const uint retry_max= 3;
167 pfs_dirty_state dirty_state;
168
169 search:
170 entry= reinterpret_cast<PFS_account**>
171 (lf_hash_search(&account_hash, pins,
172 key.m_hash_key, key.m_key_length));
173 if (entry && (entry != MY_ERRPTR))
174 {
175 pfs= *entry;
176 pfs->inc_refcount();
177 lf_hash_search_unpin(pins);
178 return pfs;
179 }
180
181 lf_hash_search_unpin(pins);
182
183 pfs= global_account_container.allocate(& dirty_state);
184 if (pfs != NULL)
185 {
186 pfs->m_key= key;
187 if (username_length > 0)
188 pfs->m_username= &pfs->m_key.m_hash_key[0];
189 else
190 pfs->m_username= NULL;
191 pfs->m_username_length= username_length;
192
193 if (hostname_length > 0)
194 pfs->m_hostname= &pfs->m_key.m_hash_key[username_length + 1];
195 else
196 pfs->m_hostname= NULL;
197 pfs->m_hostname_length= hostname_length;
198
199 pfs->m_user= find_or_create_user(thread, username, username_length);
200 pfs->m_host= find_or_create_host(thread, hostname, hostname_length);
201
202 pfs->init_refcount();
203 pfs->reset_stats();
204 pfs->m_disconnected_count= 0;
205
206 if (username_length > 0 && hostname_length > 0)
207 {
208 lookup_setup_actor(thread, username, username_length, hostname, hostname_length,
209 & pfs->m_enabled, & pfs->m_history);
210 }
211 else
212 {
213 pfs->m_enabled= true;
214 pfs->m_history= true;
215 }
216
217 int res;
218 pfs->m_lock.dirty_to_allocated(& dirty_state);
219 res= lf_hash_insert(&account_hash, pins, &pfs);
220 if (likely(res == 0))
221 {
222 return pfs;
223 }
224
225 if (pfs->m_user)
226 {
227 pfs->m_user->release();
228 pfs->m_user= NULL;
229 }
230 if (pfs->m_host)
231 {
232 pfs->m_host->release();
233 pfs->m_host= NULL;
234 }
235
236 global_account_container.deallocate(pfs);
237
238 if (res > 0)
239 {
240 if (++retry_count > retry_max)
241 {
242 global_account_container.m_lost++;
243 return NULL;
244 }
245 goto search;
246 }
247
248 global_account_container.m_lost++;
249 return NULL;
250 }
251
252 return NULL;
253 }
254
aggregate(bool alive,PFS_user * safe_user,PFS_host * safe_host)255 void PFS_account::aggregate(bool alive, PFS_user *safe_user, PFS_host *safe_host)
256 {
257 aggregate_waits(safe_user, safe_host);
258 aggregate_stages(safe_user, safe_host);
259 aggregate_statements(safe_user, safe_host);
260 aggregate_transactions(safe_user, safe_host);
261 aggregate_memory(alive, safe_user, safe_host);
262 aggregate_status(safe_user, safe_host);
263 aggregate_stats(safe_user, safe_host);
264 }
265
aggregate_waits(PFS_user * safe_user,PFS_host * safe_host)266 void PFS_account::aggregate_waits(PFS_user *safe_user, PFS_host *safe_host)
267 {
268 if (read_instr_class_waits_stats() == NULL)
269 return;
270
271 if (likely(safe_user != NULL && safe_host != NULL))
272 {
273 /*
274 Aggregate EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
275 - EVENTS_WAITS_SUMMARY_BY_USER_BY_EVENT_NAME
276 - EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME
277 in parallel.
278 */
279 aggregate_all_event_names(write_instr_class_waits_stats(),
280 safe_user->write_instr_class_waits_stats(),
281 safe_host->write_instr_class_waits_stats());
282 return;
283 }
284
285 if (safe_user != NULL)
286 {
287 /*
288 Aggregate EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
289 - EVENTS_WAITS_SUMMARY_BY_USER_BY_EVENT_NAME
290 */
291 aggregate_all_event_names(write_instr_class_waits_stats(),
292 safe_user->write_instr_class_waits_stats());
293 return;
294 }
295
296 if (safe_host != NULL)
297 {
298 /*
299 Aggregate EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
300 - EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME
301 */
302 aggregate_all_event_names(write_instr_class_waits_stats(),
303 safe_host->write_instr_class_waits_stats());
304 return;
305 }
306
307 /* Orphan account, no parent to aggregate to. */
308 reset_waits_stats();
309 return;
310 }
311
aggregate_stages(PFS_user * safe_user,PFS_host * safe_host)312 void PFS_account::aggregate_stages(PFS_user *safe_user, PFS_host *safe_host)
313 {
314 if (read_instr_class_stages_stats() == NULL)
315 return;
316
317 if (likely(safe_user != NULL && safe_host != NULL))
318 {
319 /*
320 Aggregate EVENTS_STAGES_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
321 - EVENTS_STAGES_SUMMARY_BY_USER_BY_EVENT_NAME
322 - EVENTS_STAGES_SUMMARY_BY_HOST_BY_EVENT_NAME
323 in parallel.
324 */
325 aggregate_all_stages(write_instr_class_stages_stats(),
326 safe_user->write_instr_class_stages_stats(),
327 safe_host->write_instr_class_stages_stats());
328 return;
329 }
330
331 if (safe_user != NULL)
332 {
333 /*
334 Aggregate EVENTS_STAGES_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
335 - EVENTS_STAGES_SUMMARY_BY_USER_BY_EVENT_NAME
336 - EVENTS_STAGES_SUMMARY_GLOBAL_BY_EVENT_NAME
337 in parallel.
338 */
339 aggregate_all_stages(write_instr_class_stages_stats(),
340 safe_user->write_instr_class_stages_stats(),
341 global_instr_class_stages_array);
342 return;
343 }
344
345 if (safe_host != NULL)
346 {
347 /*
348 Aggregate EVENTS_STAGES_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
349 - EVENTS_STAGES_SUMMARY_BY_HOST_BY_EVENT_NAME
350 */
351 aggregate_all_stages(write_instr_class_stages_stats(),
352 safe_host->write_instr_class_stages_stats());
353 return;
354 }
355
356 /*
357 Aggregate EVENTS_STAGES_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
358 - EVENTS_STAGES_SUMMARY_GLOBAL_BY_EVENT_NAME
359 */
360 aggregate_all_stages(write_instr_class_stages_stats(),
361 global_instr_class_stages_array);
362 return;
363 }
364
aggregate_statements(PFS_user * safe_user,PFS_host * safe_host)365 void PFS_account::aggregate_statements(PFS_user *safe_user, PFS_host *safe_host)
366 {
367 if (read_instr_class_statements_stats() == NULL)
368 return;
369
370 if (likely(safe_user != NULL && safe_host != NULL))
371 {
372 /*
373 Aggregate EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
374 - EVENTS_STATEMENTS_SUMMARY_BY_USER_BY_EVENT_NAME
375 - EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME
376 in parallel.
377 */
378 aggregate_all_statements(write_instr_class_statements_stats(),
379 safe_user->write_instr_class_statements_stats(),
380 safe_host->write_instr_class_statements_stats());
381 return;
382 }
383
384 if (safe_user != NULL)
385 {
386 /*
387 Aggregate EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
388 - EVENTS_STATEMENTS_SUMMARY_BY_USER_BY_EVENT_NAME
389 - EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME
390 in parallel.
391 */
392 aggregate_all_statements(write_instr_class_statements_stats(),
393 safe_user->write_instr_class_statements_stats(),
394 global_instr_class_statements_array);
395 return;
396 }
397
398 if (safe_host != NULL)
399 {
400 /*
401 Aggregate EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
402 - EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME
403 */
404 aggregate_all_statements(write_instr_class_statements_stats(),
405 safe_host->write_instr_class_statements_stats());
406 return;
407 }
408
409 /*
410 Aggregate EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
411 - EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME
412 */
413 aggregate_all_statements(write_instr_class_statements_stats(),
414 global_instr_class_statements_array);
415 return;
416 }
417
aggregate_transactions(PFS_user * safe_user,PFS_host * safe_host)418 void PFS_account::aggregate_transactions(PFS_user *safe_user, PFS_host *safe_host)
419 {
420 if (read_instr_class_transactions_stats() == NULL)
421 return;
422
423 if (likely(safe_user != NULL && safe_host != NULL))
424 {
425 /*
426 Aggregate EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
427 - EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME
428 - EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME
429 in parallel.
430 */
431 aggregate_all_transactions(write_instr_class_transactions_stats(),
432 safe_user->write_instr_class_transactions_stats(),
433 safe_host->write_instr_class_transactions_stats());
434 return;
435 }
436
437 if (safe_user != NULL)
438 {
439 /*
440 Aggregate EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
441 - EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME
442 - EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME
443 in parallel.
444 */
445 aggregate_all_transactions(write_instr_class_transactions_stats(),
446 safe_user->write_instr_class_transactions_stats(),
447 &global_transaction_stat);
448 return;
449 }
450
451 if (safe_host != NULL)
452 {
453 /*
454 Aggregate EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
455 - EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME
456 */
457 aggregate_all_transactions(write_instr_class_transactions_stats(),
458 safe_host->write_instr_class_transactions_stats());
459 return;
460 }
461
462 /*
463 Aggregate EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
464 - EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME
465 */
466 aggregate_all_transactions(write_instr_class_transactions_stats(),
467 &global_transaction_stat);
468 return;
469 }
470
aggregate_memory(bool alive,PFS_user * safe_user,PFS_host * safe_host)471 void PFS_account::aggregate_memory(bool alive, PFS_user *safe_user, PFS_host *safe_host)
472 {
473 if (read_instr_class_memory_stats() == NULL)
474 return;
475
476 if (likely(safe_user != NULL && safe_host != NULL))
477 {
478 /*
479 Aggregate MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
480 - MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME
481 - MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME
482 in parallel.
483 */
484 aggregate_all_memory(alive,
485 write_instr_class_memory_stats(),
486 safe_user->write_instr_class_memory_stats(),
487 safe_host->write_instr_class_memory_stats());
488 return;
489 }
490
491 if (safe_user != NULL)
492 {
493 /*
494 Aggregate MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
495 - MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME
496 - MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME
497 in parallel.
498 */
499 aggregate_all_memory(alive,
500 write_instr_class_memory_stats(),
501 safe_user->write_instr_class_memory_stats(),
502 global_instr_class_memory_array);
503 return;
504 }
505
506 if (safe_host != NULL)
507 {
508 /*
509 Aggregate MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
510 - MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME
511 */
512 aggregate_all_memory(alive,
513 write_instr_class_memory_stats(),
514 safe_host->write_instr_class_memory_stats());
515 return;
516 }
517
518 /*
519 Aggregate MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
520 - MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME
521 */
522 aggregate_all_memory(alive,
523 write_instr_class_memory_stats(),
524 global_instr_class_memory_array);
525 return;
526 }
527
aggregate_status(PFS_user * safe_user,PFS_host * safe_host)528 void PFS_account::aggregate_status(PFS_user *safe_user, PFS_host *safe_host)
529 {
530 if (likely(safe_user != NULL && safe_host != NULL))
531 {
532 /*
533 Aggregate STATUS_BY_ACCOUNT to:
534 - STATUS_BY_USER
535 - STATUS_BY_HOST
536 */
537 safe_user->m_status_stats.aggregate(& m_status_stats);
538 safe_host->m_status_stats.aggregate(& m_status_stats);
539 m_status_stats.reset();
540 return;
541 }
542
543 if (safe_user != NULL)
544 {
545 /*
546 Aggregate STATUS_BY_ACCOUNT to:
547 - STATUS_BY_USER
548 - GLOBAL_STATUS
549 */
550 safe_user->m_status_stats.aggregate(& m_status_stats);
551 m_status_stats.aggregate_to(& global_status_var);
552 m_status_stats.reset();
553 return;
554 }
555
556 if (safe_host != NULL)
557 {
558 /*
559 Aggregate STATUS_BY_ACCOUNT to:
560 - STATUS_BY_HOST
561 */
562 safe_host->m_status_stats.aggregate(& m_status_stats);
563 m_status_stats.reset();
564 return;
565 }
566
567 /*
568 Aggregate STATUS_BY_ACCOUNT to:
569 - GLOBAL_STATUS
570 */
571 m_status_stats.aggregate_to(& global_status_var);
572 m_status_stats.reset();
573 return;
574 }
575
aggregate_stats(PFS_user * safe_user,PFS_host * safe_host)576 void PFS_account::aggregate_stats(PFS_user *safe_user, PFS_host *safe_host)
577 {
578 if (likely(safe_user != NULL && safe_host != NULL))
579 {
580 safe_user->m_disconnected_count+= m_disconnected_count;
581 safe_host->m_disconnected_count+= m_disconnected_count;
582 m_disconnected_count= 0;
583 return;
584 }
585
586 if (safe_user != NULL)
587 {
588 safe_user->m_disconnected_count+= m_disconnected_count;
589 m_disconnected_count= 0;
590 return;
591 }
592
593 if (safe_host != NULL)
594 {
595 safe_host->m_disconnected_count+= m_disconnected_count;
596 m_disconnected_count= 0;
597 return;
598 }
599
600 m_disconnected_count= 0;
601 return;
602 }
603
release()604 void PFS_account::release()
605 {
606 dec_refcount();
607 }
608
carry_memory_stat_delta(PFS_memory_stat_delta * delta,uint index)609 void PFS_account::carry_memory_stat_delta(PFS_memory_stat_delta *delta, uint index)
610 {
611 PFS_memory_stat *event_name_array;
612 PFS_memory_stat *stat;
613 PFS_memory_stat_delta delta_buffer;
614 PFS_memory_stat_delta *remaining_delta;
615
616 event_name_array= write_instr_class_memory_stats();
617 stat= & event_name_array[index];
618 remaining_delta= stat->apply_delta(delta, &delta_buffer);
619
620 if (remaining_delta == NULL)
621 return;
622
623 if (m_user != NULL)
624 {
625 m_user->carry_memory_stat_delta(remaining_delta, index);
626 /* do not return, need to process m_host below */
627 }
628
629 if (m_host != NULL)
630 {
631 m_host->carry_memory_stat_delta(remaining_delta, index);
632 return;
633 }
634
635 carry_global_memory_stat_delta(remaining_delta, index);
636 }
637
sanitize_account(PFS_account * unsafe)638 PFS_account *sanitize_account(PFS_account *unsafe)
639 {
640 return global_account_container.sanitize(unsafe);
641 }
642
purge_account(PFS_thread * thread,PFS_account * account)643 void purge_account(PFS_thread *thread, PFS_account *account)
644 {
645 LF_PINS *pins= get_account_hash_pins(thread);
646 if (unlikely(pins == NULL))
647 return;
648
649 PFS_account **entry;
650 entry= reinterpret_cast<PFS_account**>
651 (lf_hash_search(&account_hash, pins,
652 account->m_key.m_hash_key,
653 account->m_key.m_key_length));
654 if (entry && (entry != MY_ERRPTR))
655 {
656 assert(*entry == account);
657 if (account->get_refcount() == 0)
658 {
659 lf_hash_delete(&account_hash, pins,
660 account->m_key.m_hash_key,
661 account->m_key.m_key_length);
662 account->aggregate(false, account->m_user, account->m_host);
663 if (account->m_user != NULL)
664 {
665 account->m_user->release();
666 account->m_user= NULL;
667 }
668 if (account->m_host != NULL)
669 {
670 account->m_host->release();
671 account->m_host= NULL;
672 }
673 global_account_container.deallocate(account);
674 }
675 }
676
677 lf_hash_search_unpin(pins);
678 }
679
680 class Proc_purge_account
681 : public PFS_buffer_processor<PFS_account>
682 {
683 public:
Proc_purge_account(PFS_thread * thread)684 Proc_purge_account(PFS_thread *thread)
685 : m_thread(thread)
686 {}
687
operator ()(PFS_account * pfs)688 virtual void operator()(PFS_account *pfs)
689 {
690 PFS_user *user= sanitize_user(pfs->m_user);
691 PFS_host *host= sanitize_host(pfs->m_host);
692 pfs->aggregate(true, user, host);
693
694 if (pfs->get_refcount() == 0)
695 purge_account(m_thread, pfs);
696 }
697
698 private:
699 PFS_thread *m_thread;
700 };
701
702 /** Purge non connected accounts, reset stats of connected account. */
purge_all_account(void)703 void purge_all_account(void)
704 {
705 PFS_thread *thread= PFS_thread::get_current_thread();
706 if (unlikely(thread == NULL))
707 return;
708
709 Proc_purge_account proc(thread);
710 global_account_container.apply(proc);
711 }
712
713 class Proc_update_accounts_derived_flags
714 : public PFS_buffer_processor<PFS_account>
715 {
716 public:
Proc_update_accounts_derived_flags(PFS_thread * thread)717 Proc_update_accounts_derived_flags(PFS_thread *thread)
718 : m_thread(thread)
719 {}
720
operator ()(PFS_account * pfs)721 virtual void operator()(PFS_account *pfs)
722 {
723 if (pfs->m_username_length > 0 && pfs->m_hostname_length > 0)
724 {
725 lookup_setup_actor(m_thread,
726 pfs->m_username, pfs->m_username_length,
727 pfs->m_hostname, pfs->m_hostname_length,
728 & pfs->m_enabled, & pfs->m_history);
729 }
730 else
731 {
732 pfs->m_enabled= true;
733 pfs->m_history= true;
734 }
735 }
736
737 private:
738 PFS_thread *m_thread;
739 };
740
update_accounts_derived_flags(PFS_thread * thread)741 void update_accounts_derived_flags(PFS_thread *thread)
742 {
743 Proc_update_accounts_derived_flags proc(thread);
744 global_account_container.apply(proc);
745 }
746
747 /** @} */
748