@@ -87,6 +87,8 @@ class ThreadContext : public Ndb_local_connection {
87
87
void deserialize_users (std::string &);
88
88
bool cache_was_rebuilt () const { return m_rebuilt_cache; }
89
89
void serialize_snapshot_user_list (std::string *out_str);
90
+ void consider_all_local_users_for_drop ();
91
+ void handle_dropped_users ();
90
92
91
93
/* NDB Transactions */
92
94
bool read_snapshot ();
@@ -136,6 +138,7 @@ class ThreadContext : public Ndb_local_connection {
136
138
Mem_root_array<char *> m_read_keys;
137
139
Mem_root_array<unsigned short > m_grant_count;
138
140
Mem_root_array<char *> m_current_rows;
141
+ Mem_root_array<char *> m_delete_users;
139
142
Mem_root_array<std::string> m_statement_users;
140
143
Mem_root_array<std::string> m_intersection;
141
144
Mem_root_array<std::string> m_extra_grants;
@@ -193,6 +196,7 @@ ThreadContext::ThreadContext(THD *thd)
193
196
m_read_keys(&mem_root),
194
197
m_grant_count(&mem_root),
195
198
m_current_rows(&mem_root),
199
+ m_delete_users(&mem_root),
196
200
m_statement_users(&mem_root),
197
201
m_intersection(&mem_root),
198
202
m_extra_grants(&mem_root),
@@ -248,10 +252,7 @@ void ThreadContext::serialize_snapshot_user_list(std::string *out_str) {
248
252
Sets m_read_keys to a set of buffers that can be used in NdbScanFilter
249
253
*/
250
254
void ThreadContext::deserialize_users (std::string &str) {
251
- /* As an optimization, prefer a complete snapshot refresh to a partial
252
- refresh of n users if n is greater than half. */
253
- int max = local_granted_users.size () / 2 ;
254
- int nfound = 0 ;
255
+ unsigned long nfound = 0 ;
255
256
256
257
for (size_t pos = 0 ; pos < str.length ();) {
257
258
/* Find the 4th quote mark in 'user'@'host' */
@@ -262,18 +263,21 @@ void ThreadContext::deserialize_users(std::string &str) {
262
263
}
263
264
size_t len = end + 1 - pos;
264
265
std::string user = str.substr (pos, len);
265
- if (get_local_user (user) && (++nfound > max)) {
266
- ndb_log_verbose (9 , " deserialize_users() choosing complete refresh" );
267
- m_read_keys.clear ();
268
- return ;
269
- }
266
+ if (get_local_user (user)) nfound++;
267
+ m_users_in_snapshot.push_back (user);
270
268
{
271
269
char *buf = getBuffer (len + 4 );
272
270
metadata_table.packName (buf, user);
273
271
m_read_keys.push_back (buf);
274
272
}
275
273
pos = end + 2 ;
276
274
}
275
+ /* As an optimization, prefer a complete snapshot refresh to a partial
276
+ refresh of n users if n is greater than half. */
277
+ if (nfound > local_granted_users.size () / 2 ) {
278
+ ndb_log_verbose (9 , " deserialize_users() choosing complete refresh" );
279
+ m_read_keys.clear ();
280
+ }
277
281
}
278
282
279
283
/* returns false on success */
@@ -483,12 +487,17 @@ const NdbError *store_snapshot(NdbTransaction *tx, ThreadContext *ctx) {
483
487
}
484
488
485
489
/* write_snapshot()
486
- m_current_rows holds a set of USER and GRANT records to be written.
490
+
487
491
m_read_keys holds a list of USER records to read.
488
492
m_grant_count holds the number of grants that will be stored for each user.
489
493
m_read_keys and m_grant_count are in one-to-one correspondence.
490
494
Any extraneous old grants for a user above m_grant_count will be deleted.
491
- After execute(), m_current_rows, m_read_keys, and m_grant_count are cleared.
495
+
496
+ m_current_rows holds a set of USER and GRANT records to be written.
497
+ m_delete_users holds a set of USER records to be deleted.
498
+
499
+ After execute(), m_current_rows, m_read_keys, m_grant_count, and
500
+ m_delete_users are all cleared.
492
501
*/
493
502
const NdbError *ThreadContext::write_snapshot (NdbTransaction *tx) {
494
503
Mem_root_array<char *> read_results (&mem_root);
@@ -522,11 +531,17 @@ const NdbError *ThreadContext::write_snapshot(NdbTransaction *tx) {
522
531
Buffer::writeTuple (row, tx);
523
532
}
524
533
534
+ /* Delete user records for DROP USER */
535
+ for (char *key : m_delete_users) {
536
+ Buffer::deleteTuple (key, tx);
537
+ }
538
+
525
539
bool r = tx->execute (Commit);
526
540
527
541
m_current_rows.clear ();
528
542
m_read_keys.clear ();
529
543
m_grant_count.clear ();
544
+ m_delete_users.clear ();
530
545
531
546
return r ? &tx->getNdbError () : nullptr ;
532
547
}
@@ -557,13 +572,13 @@ int ThreadContext::update_users(const Mem_root_array<std::string> &list) {
557
572
}
558
573
559
574
void ThreadContext::drop_user (std::string user, bool is_revoke) {
560
- std::string drop (" DROP USER IF EXISTS " );
561
- std::string revoke (" REVOKE NDB_STORED_USER ON *.* FROM " );
562
- std::string *s = is_revoke ? &revoke : &drop;
563
- std::string statement (*s + user);
564
575
unsigned int zero = 0 ;
565
-
566
- m_current_rows.push_back (Row (TYPE_USER, user, 0 , &zero, statement));
576
+ if (is_revoke) {
577
+ std::string statement (" REVOKE NDB_STORED_USER ON *.* FROM " + user);
578
+ m_current_rows.push_back (Row (TYPE_USER, user, 0 , &zero, statement));
579
+ } else {
580
+ m_delete_users.push_back (Key (TYPE_USER, user, 0 ));
581
+ }
567
582
m_read_keys.push_back (Key (TYPE_USER, user, 0 ));
568
583
m_grant_count.push_back (0 );
569
584
m_users_in_snapshot.push_back (user);
@@ -628,7 +643,8 @@ void ThreadContext::create_user(std::string &name, std::string &statement) {
628
643
run_acl_statement (revoke_all + name);
629
644
}
630
645
631
- /* Apply the snapshot in m_current_rows
646
+ /* Apply the snapshot in m_current_rows,
647
+ removing each applied user from m_users_in_snapshot.
632
648
*/
633
649
void ThreadContext::apply_current_snapshot () {
634
650
for (const char *row : m_current_rows) {
@@ -646,14 +662,15 @@ void ThreadContext::apply_current_snapshot() {
646
662
switch (type) {
647
663
case TYPE_USER:
648
664
m_applied_users++;
665
+ m_users_in_snapshot.erase_value (name);
649
666
is_null = !metadata_table.getNote (row, ¬e);
650
667
if (is_null) {
651
668
ndb_log_error (" Unexpected NULL in ndb_sql_metadata table" );
652
669
}
653
670
if (note > 0 ) {
654
671
create_user (name, statement);
655
672
} else {
656
- /* The user has been dropped , or had NDB_STORED_USER revoked */
673
+ /* REVOKE NDB_STORED_USER ON *.* FROM user , or 8.0.18 DROP USER */
657
674
if (get_local_user (name)) {
658
675
run_acl_statement (statement);
659
676
}
@@ -674,6 +691,28 @@ void ThreadContext::apply_current_snapshot() {
674
691
for (std::string grant : m_extra_grants) run_acl_statement (grant);
675
692
}
676
693
694
+ /* After apply_current_snapshot() has iteratively removed users from
695
+ m_users_in_snapshot, any user remaining there must be dropped.
696
+ */
697
+ void ThreadContext::handle_dropped_users () {
698
+ const std::string drop (" DROP USER IF EXISTS " );
699
+
700
+ for (std::string user : m_users_in_snapshot) {
701
+ ndb_log_info (" Dropping user %s not present in stored snapshot" ,
702
+ user.c_str ());
703
+ run_acl_statement (drop + user);
704
+ }
705
+ }
706
+
707
+ /* At server startup time, any local user with NDB_STORED_USER may have
708
+ been dropped while the server was down, so m_users_in_snapshot is
709
+ initialized with the whole list of local users.
710
+ */
711
+ void ThreadContext::consider_all_local_users_for_drop () {
712
+ for (std::string user : local_granted_users)
713
+ m_users_in_snapshot.push_back (user);
714
+ }
715
+
677
716
void ThreadContext::write_status_message_to_server_log () {
678
717
ndb_log_info (" From NDB stored grants, applied %zu grant%s for %zu user%s." ,
679
718
m_applied_grants, (m_applied_grants == 1 ? " " : " s" ),
@@ -862,8 +901,10 @@ bool Ndb_stored_grants::apply_stored_grants(THD *thd) {
862
901
863
902
(void )context.build_cache_of_ndb_users ();
864
903
904
+ context.consider_all_local_users_for_drop ();
865
905
context.apply_current_snapshot ();
866
906
context.write_status_message_to_server_log ();
907
+ context.handle_dropped_users ();
867
908
return true ; // success
868
909
}
869
910
@@ -916,5 +957,6 @@ bool Ndb_stored_grants::update_users_from_snapshot(THD *thd,
916
957
917
958
(void )context.build_cache_of_ndb_users ();
918
959
context.apply_current_snapshot ();
960
+ context.handle_dropped_users ();
919
961
return true ; // success
920
962
}
0 commit comments