~mdcallag/+junk/5.1-map

« back to all changes in this revision

Viewing changes to sql/sql_servers.cc

  • Committer: msvensson at pilot
  • Date: 2007-04-24 09:11:45 UTC
  • mfrom: (2469.1.106)
  • Revision ID: sp1r-msvensson@pilot.blaudden-20070424091145-10463
Merge pilot.blaudden:/home/msvensson/mysql/my51-m-mysql_upgrade
into  pilot.blaudden:/home/msvensson/mysql/mysql-5.1-maint

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
/*
18
18
  The servers are saved in the system table "servers"
 
19
  
 
20
  Currently, when the user performs an ALTER SERVER or a DROP SERVER
 
21
  operation, it will cause all open tables which refer to the named
 
22
  server connection to be flushed. This may cause some undesirable
 
23
  behaviour with regard to currently running transactions. It is 
 
24
  expected that the DBA knows what s/he is doing when s/he performs
 
25
  the ALTER SERVER or DROP SERVER operation.
 
26
  
 
27
  TODO:
 
28
  It is desirable for us to implement a callback mechanism instead where
 
29
  callbacks can be registered for specific server protocols. The callback
 
30
  will be fired when such a server name has been created/altered/dropped
 
31
  or when statistics are to be gathered such as how many actual connections.
 
32
  Storage engines etc will be able to make use of the callback so that
 
33
  currently running transactions etc will not be disrupted.
19
34
*/
20
35
 
21
36
#include "mysql_priv.h"
25
40
#include "sp_head.h"
26
41
#include "sp.h"
27
42
 
28
 
HASH servers_cache;
29
 
pthread_mutex_t servers_cache_mutex;                // To init the hash
30
 
uint servers_cache_initialised=FALSE;
31
 
/* Version of server table. incremented by servers_load */
32
 
static uint servers_version=0;
 
43
/*
 
44
  We only use 1 mutex to guard the data structures - THR_LOCK_servers.
 
45
  Read locked when only reading data and write-locked for all other access.
 
46
*/
 
47
 
 
48
static HASH servers_cache;
33
49
static MEM_ROOT mem;
34
50
static rw_lock_t THR_LOCK_servers;
35
51
 
 
52
static bool get_server_from_table_to_cache(TABLE *table);
 
53
 
 
54
/* insert functions */
 
55
static int insert_server(THD *thd, FOREIGN_SERVER *server_options);
 
56
static int insert_server_record(TABLE *table, FOREIGN_SERVER *server);
 
57
static int insert_server_record_into_cache(FOREIGN_SERVER *server);
 
58
static void prepare_server_struct_for_insert(LEX_SERVER_OPTIONS *server_options,
 
59
                                             FOREIGN_SERVER *server);
 
60
/* drop functions */ 
 
61
static int delete_server_record(TABLE *table,
 
62
                                char *server_name,
 
63
                                int server_name_length);
 
64
static int delete_server_record_in_cache(LEX_SERVER_OPTIONS *server_options);
 
65
 
 
66
/* update functions */
 
67
static void prepare_server_struct_for_update(LEX_SERVER_OPTIONS *server_options,
 
68
                                             FOREIGN_SERVER *existing,
 
69
                                             FOREIGN_SERVER *altered);
 
70
static int update_server(THD *thd, FOREIGN_SERVER *existing, 
 
71
                                             FOREIGN_SERVER *altered);
 
72
static int update_server_record(TABLE *table, FOREIGN_SERVER *server);
 
73
static int update_server_record_in_cache(FOREIGN_SERVER *existing,
 
74
                                         FOREIGN_SERVER *altered);
 
75
/* utility functions */
 
76
static void merge_server_struct(FOREIGN_SERVER *from, FOREIGN_SERVER *to);
 
77
 
 
78
 
 
79
 
36
80
static byte *servers_cache_get_key(FOREIGN_SERVER *server, uint *length,
37
81
                               my_bool not_used __attribute__((unused)))
38
82
{
45
89
  DBUG_RETURN((byte*) server->server_name);
46
90
}
47
91
 
 
92
 
48
93
/*
49
94
  Initialize structures responsible for servers used in federated
50
95
  server scheme information for them from the server
64
109
    1   Could not initialize servers
65
110
*/
66
111
 
67
 
my_bool servers_init(bool dont_read_servers_table)
 
112
bool servers_init(bool dont_read_servers_table)
68
113
{
69
114
  THD  *thd;
70
 
  my_bool return_val= 0;
 
115
  bool return_val= FALSE;
71
116
  DBUG_ENTER("servers_init");
72
117
 
73
118
  /* init the mutex */
74
 
  if (pthread_mutex_init(&servers_cache_mutex, MY_MUTEX_INIT_FAST))
75
 
    DBUG_RETURN(1);
76
 
 
77
119
  if (my_rwlock_init(&THR_LOCK_servers, NULL))
78
 
    DBUG_RETURN(1);
 
120
    DBUG_RETURN(TRUE);
79
121
 
80
122
  /* initialise our servers cache */
81
123
  if (hash_init(&servers_cache, system_charset_info, 32, 0, 0,
82
124
                (hash_get_key) servers_cache_get_key, 0, 0))
83
125
  {
84
 
    return_val= 1; /* we failed, out of memory? */
 
126
    return_val= TRUE; /* we failed, out of memory? */
85
127
    goto end;
86
128
  }
87
129
 
88
130
  /* Initialize the mem root for data */
89
131
  init_alloc_root(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
90
132
 
91
 
  /*
92
 
    at this point, the cache is initialised, let it be known
93
 
  */
94
 
  servers_cache_initialised= TRUE;
95
 
 
96
133
  if (dont_read_servers_table)
97
134
    goto end;
98
135
 
100
137
    To be able to run this from boot, we allocate a temporary THD
101
138
  */
102
139
  if (!(thd=new THD))
103
 
    DBUG_RETURN(1);
 
140
    DBUG_RETURN(TRUE);
104
141
  thd->thread_stack= (char*) &thd;
105
142
  thd->store_globals();
106
143
  /*
130
167
    TRUE   Error
131
168
*/
132
169
 
133
 
static my_bool servers_load(THD *thd, TABLE_LIST *tables)
 
170
static bool servers_load(THD *thd, TABLE_LIST *tables)
134
171
{
135
172
  TABLE *table;
136
173
  READ_RECORD read_record_info;
137
 
  my_bool return_val= TRUE;
 
174
  bool return_val= TRUE;
138
175
  DBUG_ENTER("servers_load");
139
176
 
140
 
  if (!servers_cache_initialised)
141
 
    DBUG_RETURN(0);
142
 
 
143
 
  /* need to figure out how to utilise this variable */
144
 
  servers_version++; /* servers updated */
145
 
 
146
177
  /* first, send all cached rows to sleep with the fishes, oblivion!
147
178
     I expect this crappy comment replaced */
148
179
  free_root(&mem, MYF(MY_MARK_BLOCKS_FREE));
156
187
      goto end;
157
188
  }
158
189
 
159
 
  return_val=0;
 
190
  return_val= FALSE;
160
191
 
161
192
end:
162
193
  end_read_record(&read_record_info);
183
214
    TRUE   Failure
184
215
*/
185
216
 
186
 
my_bool servers_reload(THD *thd)
 
217
bool servers_reload(THD *thd)
187
218
{
188
219
  TABLE_LIST tables[1];
189
 
  my_bool return_val= 1;
 
220
  bool return_val= TRUE;
190
221
  DBUG_ENTER("servers_reload");
191
222
 
192
223
  if (thd->locked_tables)
196
227
    close_thread_tables(thd);
197
228
  }
198
229
 
199
 
  /*
200
 
    To avoid deadlocks we should obtain table locks before
201
 
    obtaining servers_cache->lock mutex.
202
 
  */
 
230
  DBUG_PRINT("info", ("locking servers_cache"));
 
231
  rw_wrlock(&THR_LOCK_servers);
 
232
 
203
233
  bzero((char*) tables, sizeof(tables));
204
234
  tables[0].alias= tables[0].table_name= (char*) "servers";
205
235
  tables[0].db= (char*) "mysql";
207
237
 
208
238
  if (simple_open_n_lock_tables(thd, tables))
209
239
  {
210
 
    sql_print_error("Fatal error: Can't open and lock privilege tables: %s",
 
240
    sql_print_error("Can't open and lock privilege tables: %s",
211
241
                    thd->net.last_error);
212
242
    goto end;
213
243
  }
214
244
 
215
 
  DBUG_PRINT("info", ("locking servers_cache"));
216
 
  VOID(pthread_mutex_lock(&servers_cache_mutex));
217
 
 
218
 
  //old_servers_cache= servers_cache;
219
 
  //old_mem=mem;
220
 
 
221
245
  if ((return_val= servers_load(thd, tables)))
222
246
  {                                     // Error. Revert to old list
223
247
    /* blast, for now, we have no servers, discuss later way to preserve */
226
250
    servers_free();
227
251
  }
228
252
 
229
 
  DBUG_PRINT("info", ("unlocking servers_cache"));
230
 
  VOID(pthread_mutex_unlock(&servers_cache_mutex));
231
 
 
232
253
end:
233
254
  close_thread_tables(thd);
 
255
  DBUG_PRINT("info", ("unlocking servers_cache"));
 
256
  rw_unlock(&THR_LOCK_servers);
234
257
  DBUG_RETURN(return_val);
235
258
}
236
259
 
 
260
 
237
261
/*
238
262
  Initialize structures responsible for servers used in federated
239
263
  server scheme information for them from the server
260
284
    1   could not insert server struct into global servers cache
261
285
*/
262
286
 
263
 
my_bool get_server_from_table_to_cache(TABLE *table)
 
287
static bool 
 
288
get_server_from_table_to_cache(TABLE *table)
264
289
{
265
290
  /* alloc a server struct */
266
291
  char *ptr;
308
333
  DBUG_RETURN(FALSE);
309
334
}
310
335
 
311
 
/*
312
 
  SYNOPSIS
313
 
    server_exists_in_table()
314
 
      THD   *thd - thread pointer
315
 
      LEX_SERVER_OPTIONS *server_options - pointer to Lex->server_options
316
 
 
317
 
  NOTES
318
 
    This function takes a LEX_SERVER_OPTIONS struct, which is very much the
319
 
    same type of structure as a FOREIGN_SERVER, it contains the values parsed
320
 
    in any one of the [CREATE|DELETE|DROP] SERVER statements. Using the
321
 
    member "server_name", index_read_idx either founds the record and returns
322
 
    1, or doesn't find the record, and returns 0
323
 
 
324
 
  RETURN VALUES
325
 
    0   record not found
326
 
    1   record found
327
 
*/
328
 
 
329
 
my_bool server_exists_in_table(THD *thd, LEX_SERVER_OPTIONS *server_options)
330
 
{
331
 
  int result= 1;
332
 
  int error= 0;
333
 
  TABLE_LIST tables;
334
 
  TABLE *table;
335
 
  DBUG_ENTER("server_exists");
336
 
 
337
 
  bzero((char*) &tables, sizeof(tables));
338
 
  tables.db= (char*) "mysql";
339
 
  tables.alias= tables.table_name= (char*) "servers";
340
 
 
341
 
  /* need to open before acquiring THR_LOCK_plugin or it will deadlock */
342
 
  if (! (table= open_ltable(thd, &tables, TL_WRITE)))
343
 
    DBUG_RETURN(TRUE);
344
 
 
345
 
  table->use_all_columns();
346
 
 
347
 
  rw_wrlock(&THR_LOCK_servers);
348
 
  VOID(pthread_mutex_lock(&servers_cache_mutex));
349
 
 
350
 
  /* set the field that's the PK to the value we're looking for */
351
 
  table->field[0]->store(server_options->server_name,
352
 
                         server_options->server_name_length,
353
 
                         system_charset_info);
354
 
 
355
 
  if ((error= table->file->index_read_idx(table->record[0], 0,
356
 
                                   (byte *)table->field[0]->ptr,
357
 
                                   table->key_info[0].key_length,
358
 
                                   HA_READ_KEY_EXACT)))
359
 
  {
360
 
    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
361
 
    {
362
 
      table->file->print_error(error, MYF(0));
363
 
      result= -1;
364
 
    }
365
 
    result= 0;
366
 
    DBUG_PRINT("info",("record for server '%s' not found!",
367
 
                       server_options->server_name));
368
 
  }
369
 
 
370
 
  VOID(pthread_mutex_unlock(&servers_cache_mutex));
371
 
  rw_unlock(&THR_LOCK_servers);
372
 
  DBUG_RETURN(result);
373
 
}
374
336
 
375
337
/*
376
338
  SYNOPSIS
382
344
    This function takes a server object that is has all members properly
383
345
    prepared, ready to be inserted both into the mysql.servers table and
384
346
    the servers cache.
 
347
        
 
348
    THR_LOCK_servers must be write locked.
385
349
 
386
350
  RETURN VALUES
387
351
    0  - no error
388
352
    other - error code
389
353
*/
390
354
 
391
 
int insert_server(THD *thd, FOREIGN_SERVER *server)
 
355
static int 
 
356
insert_server(THD *thd, FOREIGN_SERVER *server)
392
357
{
393
 
  int error= 0;
 
358
  int error= -1;
394
359
  TABLE_LIST tables;
395
360
  TABLE *table;
396
361
 
402
367
 
403
368
  /* need to open before acquiring THR_LOCK_plugin or it will deadlock */
404
369
  if (! (table= open_ltable(thd, &tables, TL_WRITE)))
405
 
    DBUG_RETURN(TRUE);
406
 
 
407
 
  /* lock mutex to make sure no changes happen */
408
 
  VOID(pthread_mutex_lock(&servers_cache_mutex));
409
 
 
410
 
  /* lock table */
411
 
  rw_wrlock(&THR_LOCK_servers);
 
370
    goto end;
412
371
 
413
372
  /* insert the server into the table */
414
373
  if ((error= insert_server_record(table, server)))
419
378
    goto end;
420
379
 
421
380
end:
422
 
  /* unlock the table */
423
 
  rw_unlock(&THR_LOCK_servers);
424
 
  VOID(pthread_mutex_unlock(&servers_cache_mutex));
425
381
  DBUG_RETURN(error);
426
382
}
427
383
 
 
384
 
428
385
/*
429
386
  SYNOPSIS
430
387
    int insert_server_record_into_cache()
434
391
    This function takes a FOREIGN_SERVER pointer to an allocated (root mem)
435
392
    and inserts it into the global servers cache
436
393
 
 
394
    THR_LOCK_servers must be write locked.
 
395
 
437
396
  RETURN VALUE
438
397
    0   - no error
439
398
    >0  - error code
440
399
 
441
400
*/
442
401
 
443
 
int insert_server_record_into_cache(FOREIGN_SERVER *server)
 
402
static int 
 
403
insert_server_record_into_cache(FOREIGN_SERVER *server)
444
404
{
445
405
  int error=0;
446
406
  DBUG_ENTER("insert_server_record_into_cache");
461
421
  DBUG_RETURN(error);
462
422
}
463
423
 
 
424
 
464
425
/*
465
426
  SYNOPSIS
466
427
    store_server_fields()
478
439
 
479
440
*/
480
441
 
481
 
void store_server_fields(TABLE *table, FOREIGN_SERVER *server)
 
442
static void 
 
443
store_server_fields(TABLE *table, FOREIGN_SERVER *server)
482
444
{
483
445
 
484
446
  table->use_all_columns();
539
501
 
540
502
  */
541
503
 
 
504
static
542
505
int insert_server_record(TABLE *table, FOREIGN_SERVER *server)
543
506
{
544
507
  int error;
554
517
 
555
518
  /* read index until record is that specified in server_name */
556
519
  if ((error= table->file->index_read_idx(table->record[0], 0,
557
 
                                   (byte *)table->field[0]->ptr,
558
 
                                   table->key_info[0].key_length,
 
520
                                   (byte *)table->field[0]->ptr, HA_WHOLE_KEY,
559
521
                                   HA_READ_KEY_EXACT)))
560
522
  {
561
523
    /* if not found, err */
606
568
 
607
569
int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
608
570
{
609
 
  int error= 0;
 
571
  int error;
610
572
  TABLE_LIST tables;
611
573
  TABLE *table;
 
574
  LEX_STRING name= { server_options->server_name, 
 
575
                     server_options->server_name_length };
612
576
 
613
577
  DBUG_ENTER("drop_server");
614
578
  DBUG_PRINT("info", ("server name server->server_name %s",
618
582
  tables.db= (char*) "mysql";
619
583
  tables.alias= tables.table_name= (char*) "servers";
620
584
 
621
 
  /* need to open before acquiring THR_LOCK_plugin or it will deadlock */
622
 
  if (! (table= open_ltable(thd, &tables, TL_WRITE)))
623
 
    DBUG_RETURN(TRUE);
624
 
 
625
585
  rw_wrlock(&THR_LOCK_servers);
626
 
  VOID(pthread_mutex_lock(&servers_cache_mutex));
627
 
 
628
 
 
629
 
  if ((error= delete_server_record(table,
630
 
                                   server_options->server_name,
631
 
                                   server_options->server_name_length)))
632
 
    goto end;
633
 
 
634
 
 
 
586
 
 
587
  /* hit the memory hit first */
635
588
  if ((error= delete_server_record_in_cache(server_options)))
636
589
    goto end;
637
590
 
 
591
  if (! (table= open_ltable(thd, &tables, TL_WRITE)))
 
592
  {
 
593
    error= my_errno;
 
594
    goto end;
 
595
  }
 
596
 
 
597
  error= delete_server_record(table, name.str, name.length);
 
598
 
 
599
  /* close the servers table before we call closed_cached_connection_tables */
 
600
  close_thread_tables(thd);
 
601
 
 
602
  if (close_cached_connection_tables(thd, TRUE, &name))
 
603
  {
 
604
    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
605
                        ER_UNKNOWN_ERROR, "Server connection in use");
 
606
  }
 
607
 
638
608
end:
639
 
  VOID(pthread_mutex_unlock(&servers_cache_mutex));
640
609
  rw_unlock(&THR_LOCK_servers);
641
610
  DBUG_RETURN(error);
642
611
}
 
612
 
 
613
 
643
614
/*
644
615
 
645
616
  SYNOPSIS
658
629
 
659
630
*/
660
631
 
661
 
int delete_server_record_in_cache(LEX_SERVER_OPTIONS *server_options)
 
632
static int 
 
633
delete_server_record_in_cache(LEX_SERVER_OPTIONS *server_options)
662
634
{
663
 
 
664
 
  int error= 0;
 
635
  int error= ER_FOREIGN_SERVER_DOESNT_EXIST;
665
636
  FOREIGN_SERVER *server;
666
637
  DBUG_ENTER("delete_server_record_in_cache");
667
638
 
677
648
    DBUG_PRINT("info", ("server_name %s length %d not found!",
678
649
                        server_options->server_name,
679
650
                        server_options->server_name_length));
680
 
    // what should be done if not found in the cache?
 
651
    goto end;
681
652
  }
682
653
  /*
683
654
    We succeded in deletion of the server to the table, now delete
687
658
                     server->server_name,
688
659
                     server->server_name_length));
689
660
 
690
 
  if (server)
691
 
    VOID(hash_delete(&servers_cache, (byte*) server));
692
 
 
693
 
  servers_version++; /* servers updated */
694
 
 
 
661
  VOID(hash_delete(&servers_cache, (byte*) server));
 
662
  
 
663
  error= 0;
 
664
 
 
665
end:
695
666
  DBUG_RETURN(error);
696
667
}
697
668
 
 
669
 
698
670
/*
699
671
 
700
672
  SYNOPSIS
714
686
    table for the particular server via the call to update_server_record,
715
687
    and in the servers_cache via update_server_record_in_cache. 
716
688
 
 
689
    THR_LOCK_servers must be write locked.
 
690
 
717
691
  RETURN VALUE
718
692
    0 - no error
719
693
    >0 - error code
722
696
 
723
697
int update_server(THD *thd, FOREIGN_SERVER *existing, FOREIGN_SERVER *altered)
724
698
{
725
 
  int error= 0;
 
699
  int error;
726
700
  TABLE *table;
727
701
  TABLE_LIST tables;
728
702
  DBUG_ENTER("update_server");
732
706
  tables.alias= tables.table_name= (char*)"servers";
733
707
 
734
708
  if (!(table= open_ltable(thd, &tables, TL_WRITE)))
735
 
    DBUG_RETURN(1);
 
709
  {
 
710
    error= my_errno;
 
711
    goto end;
 
712
  }
736
713
 
737
 
  rw_wrlock(&THR_LOCK_servers);
738
714
  if ((error= update_server_record(table, altered)))
739
715
    goto end;
740
716
 
741
 
  update_server_record_in_cache(existing, altered);
 
717
  error= update_server_record_in_cache(existing, altered);
 
718
 
 
719
  /*
 
720
        Perform a reload so we don't have a 'hole' in our mem_root
 
721
  */
 
722
  servers_load(thd, &tables);
742
723
 
743
724
end:
744
 
  rw_unlock(&THR_LOCK_servers);
745
725
  DBUG_RETURN(error);
746
726
}
747
727
 
 
728
 
748
729
/*
749
730
 
750
731
  SYNOPSIS
761
742
    HASH, then the updated record inserted, in essence replacing the old
762
743
    record.
763
744
 
 
745
    THR_LOCK_servers must be write locked.
 
746
 
764
747
  RETURN VALUE
765
748
    0 - no error
766
749
    1 - error
791
774
  {
792
775
    DBUG_PRINT("info", ("had a problem inserting server %s at %lx",
793
776
                        altered->server_name, (long unsigned int) altered));
794
 
    error= 1;
 
777
    error= ER_OUT_OF_RESOURCES;
795
778
  }
796
779
 
797
 
  servers_version++; /* servers updated */
798
780
  DBUG_RETURN(error);
799
781
}
800
782
 
 
783
 
801
784
/*
802
785
 
803
786
  SYNOPSIS
830
813
    to->password= strdup_root(&mem, from->password);
831
814
  if (to->port == -1)
832
815
    to->port= from->port;
833
 
  if (!to->socket)
 
816
  if (!to->socket && from->socket)
834
817
    to->socket= strdup_root(&mem, from->socket);
835
 
  if (!to->scheme)
 
818
  if (!to->scheme && from->scheme)
836
819
    to->scheme= strdup_root(&mem, from->scheme);
837
820
  if (!to->owner)
838
821
    to->owner= strdup_root(&mem, from->owner);
840
823
  DBUG_VOID_RETURN;
841
824
}
842
825
 
 
826
 
843
827
/*
844
828
 
845
829
  SYNOPSIS
862
846
 
863
847
*/
864
848
 
865
 
int update_server_record(TABLE *table, FOREIGN_SERVER *server)
 
849
 
 
850
static int 
 
851
update_server_record(TABLE *table, FOREIGN_SERVER *server)
866
852
{
867
853
  int error=0;
868
854
  DBUG_ENTER("update_server_record");
873
859
                         system_charset_info);
874
860
 
875
861
  if ((error= table->file->index_read_idx(table->record[0], 0,
876
 
                                   (byte *)table->field[0]->ptr,
877
 
                                   table->key_info[0].key_length,
 
862
                                   (byte *)table->field[0]->ptr, ~(longlong)0,
878
863
                                   HA_READ_KEY_EXACT)))
879
864
  {
880
865
    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
881
 
    {
882
866
      table->file->print_error(error, MYF(0));
883
 
      error= 1;
884
 
    }
885
867
    DBUG_PRINT("info",("server not found!"));
886
868
    error= ER_FOREIGN_SERVER_DOESNT_EXIST;
887
869
  }
901
883
  DBUG_RETURN(error);
902
884
}
903
885
 
 
886
 
904
887
/*
905
888
 
906
889
  SYNOPSIS
916
899
 
917
900
*/
918
901
 
919
 
int delete_server_record(TABLE *table,
920
 
                         char *server_name,
921
 
                         int server_name_length)
 
902
static int 
 
903
delete_server_record(TABLE *table,
 
904
                     char *server_name, int server_name_length)
922
905
{
923
 
  int error= 0;
 
906
  int error;
924
907
  DBUG_ENTER("delete_server_record");
925
908
  table->use_all_columns();
926
909
 
928
911
  table->field[0]->store(server_name, server_name_length, system_charset_info);
929
912
 
930
913
  if ((error= table->file->index_read_idx(table->record[0], 0,
931
 
                                   (byte *)table->field[0]->ptr,
932
 
                                   table->key_info[0].key_length,
 
914
                                   (byte *)table->field[0]->ptr, HA_WHOLE_KEY,
933
915
                                   HA_READ_KEY_EXACT)))
934
916
  {
935
917
    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
936
 
    {
937
918
      table->file->print_error(error, MYF(0));
938
 
      error= 1;
939
 
    }
940
919
    DBUG_PRINT("info",("server not found!"));
941
920
    error= ER_FOREIGN_SERVER_DOESNT_EXIST;
942
921
  }
965
944
 
966
945
int create_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
967
946
{
968
 
  int error;
 
947
  int error= ER_FOREIGN_SERVER_EXISTS;
969
948
  FOREIGN_SERVER *server;
970
949
 
971
950
  DBUG_ENTER("create_server");
972
951
  DBUG_PRINT("info", ("server_options->server_name %s",
973
952
                      server_options->server_name));
974
953
 
 
954
  rw_wrlock(&THR_LOCK_servers);
 
955
 
 
956
  /* hit the memory first */
 
957
  if (hash_search(&servers_cache, (byte*) server_options->server_name,
 
958
                                   server_options->server_name_length))
 
959
    goto end;
 
960
 
975
961
  server= (FOREIGN_SERVER *)alloc_root(&mem,
976
962
                                       sizeof(FOREIGN_SERVER));
977
963
 
978
 
  if ((error= prepare_server_struct_for_insert(server_options, server)))
979
 
    goto end;
 
964
  prepare_server_struct_for_insert(server_options, server);
980
965
 
981
 
  if ((error= insert_server(thd, server)))
982
 
    goto end;
 
966
  error= insert_server(thd, server);
983
967
 
984
968
  DBUG_PRINT("info", ("error returned %d", error));
985
969
 
986
970
end:
 
971
  rw_unlock(&THR_LOCK_servers);
987
972
  DBUG_RETURN(error);
988
973
}
989
974
 
 
975
 
990
976
/*
991
977
 
992
978
  SYNOPSIS
1003
989
 
1004
990
int alter_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
1005
991
{
1006
 
  int error= 0;
 
992
  int error= ER_FOREIGN_SERVER_DOESNT_EXIST;
1007
993
  FOREIGN_SERVER *altered, *existing;
 
994
  LEX_STRING name= { server_options->server_name, 
 
995
                     server_options->server_name_length };
1008
996
  DBUG_ENTER("alter_server");
1009
997
  DBUG_PRINT("info", ("server_options->server_name %s",
1010
998
                      server_options->server_name));
1011
999
 
 
1000
  rw_wrlock(&THR_LOCK_servers);
 
1001
 
 
1002
  if (!(existing= (FOREIGN_SERVER *) hash_search(&servers_cache,
 
1003
                                                 (byte*) name.str,
 
1004
                                                 name.length)))
 
1005
    goto end;
 
1006
 
1012
1007
  altered= (FOREIGN_SERVER *)alloc_root(&mem,
1013
1008
                                        sizeof(FOREIGN_SERVER));
1014
1009
 
1015
 
  VOID(pthread_mutex_lock(&servers_cache_mutex));
1016
 
 
1017
 
  if (!(existing= (FOREIGN_SERVER *) hash_search(&servers_cache,
1018
 
                                                 (byte*) server_options->server_name,
1019
 
                                               server_options->server_name_length)))
 
1010
  prepare_server_struct_for_update(server_options, existing, altered);
 
1011
 
 
1012
  error= update_server(thd, existing, altered);
 
1013
 
 
1014
  /* close the servers table before we call closed_cached_connection_tables */
 
1015
  close_thread_tables(thd);
 
1016
 
 
1017
  if (close_cached_connection_tables(thd, FALSE, &name))
1020
1018
  {
1021
 
    error= ER_FOREIGN_SERVER_DOESNT_EXIST;
1022
 
    goto end;
 
1019
    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
1020
                        ER_UNKNOWN_ERROR, "Server connection in use");
1023
1021
  }
1024
1022
 
1025
 
  if ((error= prepare_server_struct_for_update(server_options, existing, altered)))
1026
 
    goto end;
1027
 
 
1028
 
  if ((error= update_server(thd, existing, altered)))
1029
 
    goto end;
1030
 
 
1031
1023
end:
1032
1024
  DBUG_PRINT("info", ("error returned %d", error));
1033
 
  VOID(pthread_mutex_unlock(&servers_cache_mutex));
 
1025
  rw_unlock(&THR_LOCK_servers);
1034
1026
  DBUG_RETURN(error);
1035
1027
}
1036
1028
 
 
1029
 
1037
1030
/*
1038
1031
 
1039
1032
  SYNOPSIS
1044
1037
  NOTES
1045
1038
 
1046
1039
  RETURN VALUE
1047
 
    0 - no error
 
1040
    none
1048
1041
 
1049
1042
*/
1050
1043
 
1051
 
int prepare_server_struct_for_insert(LEX_SERVER_OPTIONS *server_options,
1052
 
                                     FOREIGN_SERVER *server)
 
1044
static void
 
1045
prepare_server_struct_for_insert(LEX_SERVER_OPTIONS *server_options,
 
1046
                                 FOREIGN_SERVER *server)
1053
1047
{
1054
 
  int error;
1055
1048
  char *unset_ptr= (char*)"";
1056
1049
  DBUG_ENTER("prepare_server_struct");
1057
1050
 
1058
 
  error= 0;
1059
 
 
1060
1051
  /* these two MUST be set */
1061
1052
  server->server_name= strdup_root(&mem, server_options->server_name);
1062
1053
  server->server_name_length= server_options->server_name_length;
1086
1077
  server->owner= server_options->owner ?
1087
1078
    strdup_root(&mem, server_options->owner) : unset_ptr;
1088
1079
 
1089
 
  DBUG_RETURN(error);
 
1080
  DBUG_VOID_RETURN;
1090
1081
}
1091
1082
 
1092
1083
/*
1102
1093
 
1103
1094
*/
1104
1095
 
1105
 
int prepare_server_struct_for_update(LEX_SERVER_OPTIONS *server_options,
1106
 
                                     FOREIGN_SERVER *existing,
1107
 
                                     FOREIGN_SERVER *altered)
 
1096
static void
 
1097
prepare_server_struct_for_update(LEX_SERVER_OPTIONS *server_options,
 
1098
                                 FOREIGN_SERVER *existing,
 
1099
                                 FOREIGN_SERVER *altered)
1108
1100
{
1109
 
  int error;
1110
1101
  DBUG_ENTER("prepare_server_struct_for_update");
1111
 
  error= 0;
1112
1102
 
1113
1103
  altered->server_name= strdup_root(&mem, server_options->server_name);
1114
1104
  altered->server_name_length= server_options->server_name_length;
1159
1149
    (strcmp(server_options->owner, existing->owner))) ?
1160
1150
      strdup_root(&mem, server_options->owner) : 0;
1161
1151
 
1162
 
  DBUG_RETURN(error);
 
1152
  DBUG_VOID_RETURN;
1163
1153
}
1164
1154
 
1165
1155
/*
1178
1168
void servers_free(bool end)
1179
1169
{
1180
1170
  DBUG_ENTER("servers_free");
1181
 
  if (!servers_cache_initialised)
1182
 
    DBUG_VOID_RETURN;
1183
 
  VOID(pthread_mutex_destroy(&servers_cache_mutex));
1184
 
  servers_cache_initialised=0;
 
1171
  if (!hash_inited(&servers_cache))
 
1172
    DBUG_VOID_RETURN;
 
1173
  if (!end)
 
1174
  {
 
1175
    free_root(&mem, MYF(MY_MARK_BLOCKS_FREE));
 
1176
        my_hash_reset(&servers_cache);
 
1177
    DBUG_VOID_RETURN;
 
1178
  }
 
1179
  rwlock_destroy(&THR_LOCK_servers);
1185
1180
  free_root(&mem,MYF(0));
1186
1181
  hash_free(&servers_cache);
1187
1182
  DBUG_VOID_RETURN;
1188
1183
}
1189
1184
 
1190
1185
 
 
1186
/*
 
1187
  SYNOPSIS
 
1188
 
 
1189
  clone_server(MEM_ROOT *mem_root, FOREIGN_SERVER *orig, FOREIGN_SERVER *buff)
 
1190
 
 
1191
  Create a clone of FOREIGN_SERVER. If the supplied mem_root is of
 
1192
  thd->mem_root then the copy is automatically disposed at end of statement.
 
1193
 
 
1194
  NOTES
 
1195
 
 
1196
  ARGS
 
1197
   MEM_ROOT pointer (strings are copied into this mem root) 
 
1198
   FOREIGN_SERVER pointer (made a copy of)
 
1199
   FOREIGN_SERVER buffer (if not-NULL, this pointer is returned)
 
1200
 
 
1201
  RETURN VALUE
 
1202
   FOREIGN_SEVER pointer (copy of one supplied FOREIGN_SERVER)
 
1203
*/
 
1204
 
 
1205
static FOREIGN_SERVER *clone_server(MEM_ROOT *mem, const FOREIGN_SERVER *server,
 
1206
                                    FOREIGN_SERVER *buffer)
 
1207
{
 
1208
  DBUG_ENTER("sql_server.cc:clone_server");
 
1209
 
 
1210
  if (!buffer)
 
1211
    buffer= (FOREIGN_SERVER *) alloc_root(mem, sizeof(FOREIGN_SERVER));
 
1212
 
 
1213
  buffer->server_name= strmake_root(mem, server->server_name,
 
1214
                                    server->server_name_length);
 
1215
  buffer->port= server->port;
 
1216
  buffer->server_name_length= server->server_name_length;
 
1217
  
 
1218
  /* TODO: We need to examine which of these can really be NULL */
 
1219
  buffer->db= server->db ? strdup_root(mem, server->db) : NULL;
 
1220
  buffer->scheme= server->scheme ? strdup_root(mem, server->scheme) : NULL;
 
1221
  buffer->username= server->username? strdup_root(mem, server->username): NULL;
 
1222
  buffer->password= server->password? strdup_root(mem, server->password): NULL;
 
1223
  buffer->socket= server->socket ? strdup_root(mem, server->socket) : NULL;
 
1224
  buffer->owner= server->owner ? strdup_root(mem, server->owner) : NULL;
 
1225
  buffer->host= server->host ? strdup_root(mem, server->host) : NULL;
 
1226
 
 
1227
 DBUG_RETURN(buffer);
 
1228
}
 
1229
 
1191
1230
 
1192
1231
/*
1193
1232
 
1202
1241
 
1203
1242
*/
1204
1243
 
1205
 
FOREIGN_SERVER *get_server_by_name(const char *server_name)
 
1244
FOREIGN_SERVER *get_server_by_name(MEM_ROOT *mem, const char *server_name,
 
1245
                                   FOREIGN_SERVER *buff)
1206
1246
{
1207
 
  ulong error_num=0;
1208
1247
  uint server_name_length;
1209
 
  FOREIGN_SERVER *server= 0;
 
1248
  FOREIGN_SERVER *server;
1210
1249
  DBUG_ENTER("get_server_by_name");
1211
1250
  DBUG_PRINT("info", ("server_name %s", server_name));
1212
1251
 
1215
1254
  if (! server_name || !strlen(server_name))
1216
1255
  {
1217
1256
    DBUG_PRINT("info", ("server_name not defined!"));
1218
 
    error_num= 1;
1219
1257
    DBUG_RETURN((FOREIGN_SERVER *)NULL);
1220
1258
  }
1221
1259
 
1222
1260
  DBUG_PRINT("info", ("locking servers_cache"));
1223
 
  VOID(pthread_mutex_lock(&servers_cache_mutex));
 
1261
  rw_rdlock(&THR_LOCK_servers);
1224
1262
  if (!(server= (FOREIGN_SERVER *) hash_search(&servers_cache,
1225
1263
                                               (byte*) server_name,
1226
1264
                                               server_name_length)))
1229
1267
                        server_name, server_name_length));
1230
1268
    server= (FOREIGN_SERVER *) NULL;
1231
1269
  }
 
1270
  /* otherwise, make copy of server */
 
1271
  else
 
1272
    server= clone_server(mem, server, buff);
 
1273
 
1232
1274
  DBUG_PRINT("info", ("unlocking servers_cache"));
1233
 
  VOID(pthread_mutex_unlock(&servers_cache_mutex));
 
1275
  rw_unlock(&THR_LOCK_servers);
1234
1276
  DBUG_RETURN(server);
1235
1277
 
1236
1278
}