~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

  • Committer: Brian Aker
  • Date: 2010-05-07 06:18:08 UTC
  • mto: (1527.1.1 staging)
  • mto: This revision was merged to the branch mainline in revision 1526.
  • Revision ID: brian@gaz-20100507061808-xtbz9dgb32o783yg
Remove members to functions that are no longer used.

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
#include <drizzled/lock.h>
40
40
#include <drizzled/item/return_date_time.h>
41
41
#include <drizzled/item/empty_string.h>
42
 
#include "drizzled/session/cache.h"
 
42
#include "drizzled/plugin/registry.h"
 
43
#include "drizzled/session_list.h"
43
44
#include <drizzled/message/schema.pb.h>
44
45
#include <drizzled/plugin/client.h>
45
46
#include <drizzled/cached_directory.h>
48
49
#include "drizzled/pthread_globals.h"
49
50
#include "drizzled/internal/m_string.h"
50
51
#include "drizzled/internal/my_sys.h"
51
 
#include "drizzled/message/statement_transform.h"
52
 
 
53
52
 
54
53
#include <sys/stat.h>
55
54
 
70
69
  return str ? str : "<nil>";
71
70
}
72
71
 
 
72
static void store_key_options(String *packet, Table *table, KEY *key_info);
 
73
 
 
74
 
73
75
int wild_case_compare(const CHARSET_INFO * const cs, const char *str, const char *wildstr)
74
76
{
75
77
  register int flag;
118
120
  return (*str != '\0');
119
121
}
120
122
 
 
123
 
 
124
bool drizzled_show_create(Session *session, TableList *table_list, bool is_if_not_exists)
 
125
{
 
126
  char buff[2048];
 
127
  String buffer(buff, sizeof(buff), system_charset_info);
 
128
 
 
129
  /* Only one table for now, but VIEW can involve several tables */
 
130
  if (session->openTables(table_list))
 
131
  {
 
132
    if (session->is_error())
 
133
      return true;
 
134
 
 
135
    /*
 
136
      Clear all messages with 'error' level status and
 
137
      issue a warning with 'warning' level status in
 
138
      case of invalid view and last error is ER_VIEW_INVALID
 
139
    */
 
140
    drizzle_reset_errors(session, true);
 
141
    session->clear_error();
 
142
  }
 
143
 
 
144
  buffer.length(0);
 
145
 
 
146
  if (store_create_info(table_list, &buffer, is_if_not_exists))
 
147
    return true;
 
148
 
 
149
  List<Item> field_list;
 
150
  {
 
151
    field_list.push_back(new Item_empty_string("Table",NAME_CHAR_LEN));
 
152
    // 1024 is for not to confuse old clients
 
153
    field_list.push_back(new Item_empty_string("Create Table",
 
154
                                               max(buffer.length(),(uint32_t)1024)));
 
155
  }
 
156
 
 
157
  if (session->client->sendFields(&field_list))
 
158
    return true;
 
159
  {
 
160
    session->client->store(table_list->table->alias);
 
161
  }
 
162
 
 
163
  session->client->store(buffer.ptr(), buffer.length());
 
164
 
 
165
  if (session->client->flush())
 
166
    return true;
 
167
 
 
168
  session->my_eof();
 
169
  return false;
 
170
}
 
171
 
 
172
/**
 
173
  Get a CREATE statement for a given database.
 
174
 
 
175
  The database is identified by its name, passed as @c dbname parameter.
 
176
  The name should be encoded using the system character set (UTF8 currently).
 
177
 
 
178
  Resulting statement is stored in the string pointed by @c buffer. The string
 
179
  is emptied first and its character set is set to the system character set.
 
180
 
 
181
  If is_if_not_exists is set, then
 
182
  the resulting CREATE statement contains "IF NOT EXISTS" clause. Other flags
 
183
  in @c create_options are ignored.
 
184
 
 
185
  @param  session           The current thread instance.
 
186
  @param  dbname        The name of the database.
 
187
  @param  buffer        A String instance where the statement is stored.
 
188
  @param  create_info   If not NULL, the options member influences the resulting
 
189
                        CRATE statement.
 
190
 
 
191
  @returns true if errors are detected, false otherwise.
 
192
*/
 
193
 
 
194
static bool store_db_create_info(SchemaIdentifier &schema_identifier, string &buffer, bool if_not_exists)
 
195
{
 
196
  message::Schema schema;
 
197
 
 
198
  bool found= plugin::StorageEngine::getSchemaDefinition(schema_identifier, schema);
 
199
  if (not found)
 
200
    return false;
 
201
 
 
202
  buffer.append("CREATE DATABASE ");
 
203
 
 
204
  if (if_not_exists)
 
205
    buffer.append("IF NOT EXISTS ");
 
206
 
 
207
  buffer.append("`");
 
208
  buffer.append(schema.name());
 
209
  buffer.append("`");
 
210
 
 
211
  if (schema.has_collation())
 
212
  {
 
213
    buffer.append(" COLLATE = ");
 
214
    buffer.append(schema.collation());
 
215
  }
 
216
 
 
217
  return true;
 
218
}
 
219
 
 
220
bool mysqld_show_create_db(Session &session, SchemaIdentifier &schema_identifier, bool if_not_exists)
 
221
{
 
222
  message::Schema schema_message;
 
223
  string buffer;
 
224
 
 
225
  if (not plugin::StorageEngine::getSchemaDefinition(schema_identifier, schema_message))
 
226
  {
 
227
    /*
 
228
      This assumes that the only reason for which store_db_create_info()
 
229
      can fail is incorrect database name (which is the case now).
 
230
    */
 
231
    my_error(ER_BAD_DB_ERROR, MYF(0), schema_identifier.getSQLPath().c_str());
 
232
    return true;
 
233
  }
 
234
 
 
235
  if (not store_db_create_info(schema_identifier, buffer, if_not_exists))
 
236
  {
 
237
    /*
 
238
      This assumes that the only reason for which store_db_create_info()
 
239
      can fail is incorrect database name (which is the case now).
 
240
    */
 
241
    my_error(ER_BAD_DB_ERROR, MYF(0), schema_identifier.getSQLPath().c_str());
 
242
    return true;
 
243
  }
 
244
 
 
245
  List<Item> field_list;
 
246
  field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
 
247
  field_list.push_back(new Item_empty_string("Create Database",1024));
 
248
 
 
249
  if (session.client->sendFields(&field_list))
 
250
    return true;
 
251
 
 
252
  session.client->store(schema_message.name());
 
253
  session.client->store(buffer);
 
254
 
 
255
  if (session.client->flush())
 
256
    return true;
 
257
 
 
258
  session.my_eof();
 
259
 
 
260
  return false;
 
261
}
 
262
 
121
263
/*
122
264
  Get the quote character for displaying an identifier.
123
265
 
143
285
  return '`';
144
286
}
145
287
 
 
288
 
 
289
#define LIST_PROCESS_HOST_LEN 64
 
290
 
 
291
static bool get_field_default_value(Field *timestamp_field,
 
292
                                    Field *field, String *def_value,
 
293
                                    bool quoted)
 
294
{
 
295
  bool has_default;
 
296
  bool has_now_default;
 
297
 
 
298
  /*
 
299
     We are using CURRENT_TIMESTAMP instead of NOW because it is
 
300
     more standard
 
301
  */
 
302
  has_now_default= (timestamp_field == field &&
 
303
                    field->unireg_check != Field::TIMESTAMP_UN_FIELD);
 
304
 
 
305
  has_default= (field->type() != DRIZZLE_TYPE_BLOB &&
 
306
                !(field->flags & NO_DEFAULT_VALUE_FLAG) &&
 
307
                field->unireg_check != Field::NEXT_NUMBER);
 
308
 
 
309
  def_value->length(0);
 
310
  if (has_default)
 
311
  {
 
312
    if (has_now_default)
 
313
      def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
 
314
    else if (!field->is_null())
 
315
    {                                             // Not null by default
 
316
      char tmp[MAX_FIELD_WIDTH];
 
317
      String type(tmp, sizeof(tmp), field->charset());
 
318
      field->val_str(&type);
 
319
      if (type.length())
 
320
      {
 
321
        String def_val;
 
322
        uint32_t dummy_errors;
 
323
        /* convert to system_charset_info == utf8 */
 
324
        def_val.copy(type.ptr(), type.length(), field->charset(),
 
325
                     system_charset_info, &dummy_errors);
 
326
        if (quoted)
 
327
          append_unescaped(def_value, def_val.ptr(), def_val.length());
 
328
        else
 
329
          def_value->append(def_val.ptr(), def_val.length());
 
330
      }
 
331
      else if (quoted)
 
332
        def_value->append(STRING_WITH_LEN("''"));
 
333
    }
 
334
    else if (field->maybe_null() && quoted)
 
335
      def_value->append(STRING_WITH_LEN("NULL"));    // Null as default
 
336
    else
 
337
      return false;
 
338
  }
 
339
  return has_default;
 
340
}
 
341
 
 
342
/*
 
343
  Build a CREATE TABLE statement for a table.
 
344
 
 
345
  SYNOPSIS
 
346
    store_create_info()
 
347
    table_list        A list containing one table to write statement
 
348
                      for.
 
349
    packet            Pointer to a string where statement will be
 
350
                      written.
 
351
 
 
352
  NOTE
 
353
    Currently always return 0, but might return error code in the
 
354
    future.
 
355
 
 
356
  RETURN
 
357
    0       OK
 
358
 */
 
359
 
 
360
int store_create_info(TableList *table_list, String *packet, bool is_if_not_exists)
 
361
{
 
362
  List<Item> field_list;
 
363
  char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH];
 
364
  const char *alias;
 
365
  string buff;
 
366
  String type(tmp, sizeof(tmp), system_charset_info);
 
367
  String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info);
 
368
  Field **ptr,*field;
 
369
  uint32_t primary_key;
 
370
  KEY *key_info;
 
371
  Table *table= table_list->table;
 
372
  Cursor *cursor= table->cursor;
 
373
  TableShare *share= table->s;
 
374
  HA_CREATE_INFO create_info;
 
375
  bool show_table_options= false;
 
376
  my_bitmap_map *old_map;
 
377
 
 
378
  table->restoreRecordAsDefault(); // Get empty record
 
379
 
 
380
  if (share->tmp_table)
 
381
    packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
 
382
  else
 
383
    packet->append(STRING_WITH_LEN("CREATE TABLE "));
 
384
  if (is_if_not_exists)
 
385
    packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
 
386
  alias= share->getTableName();
 
387
 
 
388
  packet->append_identifier(alias, strlen(alias));
 
389
  packet->append(STRING_WITH_LEN(" (\n"));
 
390
  /*
 
391
    We need this to get default values from the table
 
392
    We have to restore the read_set if we are called from insert in case
 
393
    of row based replication.
 
394
  */
 
395
  old_map= table->use_all_columns(table->read_set);
 
396
 
 
397
  for (ptr=table->field ; (field= *ptr); ptr++)
 
398
  {
 
399
    uint32_t flags = field->flags;
 
400
 
 
401
    if (ptr != table->field)
 
402
      packet->append(STRING_WITH_LEN(",\n"));
 
403
 
 
404
    packet->append(STRING_WITH_LEN("  "));
 
405
    packet->append_identifier(field->field_name, strlen(field->field_name));
 
406
    packet->append(' ');
 
407
    // check for surprises from the previous call to Field::sql_type()
 
408
    if (type.ptr() != tmp)
 
409
      type.set(tmp, sizeof(tmp), system_charset_info);
 
410
    else
 
411
      type.set_charset(system_charset_info);
 
412
 
 
413
    field->sql_type(type);
 
414
    packet->append(type.ptr(), type.length(), system_charset_info);
 
415
 
 
416
    if (field->has_charset())
 
417
    {
 
418
      /*
 
419
        For string types dump collation name only if
 
420
        collation is not primary for the given charset
 
421
      */
 
422
      if (!(field->charset()->state & MY_CS_PRIMARY))
 
423
      {
 
424
        packet->append(STRING_WITH_LEN(" COLLATE "));
 
425
        packet->append(field->charset()->name);
 
426
      }
 
427
    }
 
428
 
 
429
    if (flags & NOT_NULL_FLAG)
 
430
      packet->append(STRING_WITH_LEN(" NOT NULL"));
 
431
    else if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
 
432
    {
 
433
      /*
 
434
        TIMESTAMP field require explicit NULL flag, because unlike
 
435
        all other fields they are treated as NOT NULL by default.
 
436
      */
 
437
      packet->append(STRING_WITH_LEN(" NULL"));
 
438
    }
 
439
    {
 
440
      /*
 
441
        Add field flags about FIELD FORMAT (FIXED or DYNAMIC)
 
442
        and about STORAGE (DISK or MEMORY).
 
443
      */
 
444
      enum column_format_type column_format= (enum column_format_type)
 
445
        ((flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
 
446
      if (column_format)
 
447
      {
 
448
        packet->append(STRING_WITH_LEN(" /*!"));
 
449
        packet->append(STRING_WITH_LEN(" COLUMN_FORMAT"));
 
450
        if (column_format == COLUMN_FORMAT_TYPE_FIXED)
 
451
          packet->append(STRING_WITH_LEN(" FIXED */"));
 
452
        else
 
453
          packet->append(STRING_WITH_LEN(" DYNAMIC */"));
 
454
      }
 
455
    }
 
456
    if (get_field_default_value(table->timestamp_field, field, &def_value, 1))
 
457
    {
 
458
      packet->append(STRING_WITH_LEN(" DEFAULT "));
 
459
      packet->append(def_value.ptr(), def_value.length(), system_charset_info);
 
460
    }
 
461
 
 
462
    if (table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD)
 
463
      packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
 
464
 
 
465
    if (field->unireg_check == Field::NEXT_NUMBER)
 
466
      packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
 
467
 
 
468
    if (field->comment.length)
 
469
    {
 
470
      packet->append(STRING_WITH_LEN(" COMMENT "));
 
471
      append_unescaped(packet, field->comment.str, field->comment.length);
 
472
    }
 
473
  }
 
474
 
 
475
  key_info= table->key_info;
 
476
  memset(&create_info, 0, sizeof(create_info));
 
477
  /* Allow update_create_info to update row type */
 
478
  create_info.row_type= share->row_type;
 
479
  cursor->update_create_info(&create_info);
 
480
  primary_key= share->primary_key;
 
481
 
 
482
  for (uint32_t i=0 ; i < share->keys ; i++,key_info++)
 
483
  {
 
484
    KEY_PART_INFO *key_part= key_info->key_part;
 
485
    bool found_primary=0;
 
486
    packet->append(STRING_WITH_LEN(",\n  "));
 
487
 
 
488
    if (i == primary_key && is_primary_key(key_info))
 
489
    {
 
490
      found_primary=1;
 
491
      /*
 
492
        No space at end, because a space will be added after where the
 
493
        identifier would go, but that is not added for primary key.
 
494
      */
 
495
      packet->append(STRING_WITH_LEN("PRIMARY KEY"));
 
496
    }
 
497
    else if (key_info->flags & HA_NOSAME)
 
498
      packet->append(STRING_WITH_LEN("UNIQUE KEY "));
 
499
    else
 
500
      packet->append(STRING_WITH_LEN("KEY "));
 
501
 
 
502
    if (!found_primary)
 
503
     packet->append_identifier(key_info->name, strlen(key_info->name));
 
504
 
 
505
    packet->append(STRING_WITH_LEN(" ("));
 
506
 
 
507
    for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
 
508
    {
 
509
      if (j)
 
510
        packet->append(',');
 
511
 
 
512
      if (key_part->field)
 
513
        packet->append_identifier(key_part->field->field_name,
 
514
                                  strlen(key_part->field->field_name));
 
515
      if (key_part->field &&
 
516
          (key_part->length !=
 
517
           table->field[key_part->fieldnr-1]->key_length()))
 
518
      {
 
519
        buff.assign("(");
 
520
        buff.append(to_string((int32_t) key_part->length /
 
521
                              key_part->field->charset()->mbmaxlen));
 
522
        buff.append(")");
 
523
        packet->append(buff.c_str(), buff.length());
 
524
      }
 
525
    }
 
526
    packet->append(')');
 
527
    store_key_options(packet, table, key_info);
 
528
  }
 
529
 
 
530
  /*
 
531
    Get possible foreign key definitions stored in InnoDB and append them
 
532
    to the CREATE TABLE statement
 
533
  */
 
534
 
 
535
  if ((for_str= cursor->get_foreign_key_create_info()))
 
536
  {
 
537
    packet->append(for_str, strlen(for_str));
 
538
    cursor->free_foreign_key_create_info(for_str);
 
539
  }
 
540
 
 
541
  packet->append(STRING_WITH_LEN("\n)"));
 
542
  {
 
543
    show_table_options= true;
 
544
    /*
 
545
      Get possible table space definitions and append them
 
546
      to the CREATE TABLE statement
 
547
    */
 
548
 
 
549
    /* 
 
550
      We should always store engine since we will now be 
 
551
      making sure engines accept options (aka... no
 
552
      dangling arguments for engines.
 
553
    */
 
554
    packet->append(STRING_WITH_LEN(" ENGINE="));
 
555
    packet->append(cursor->getEngine()->getName().c_str());
 
556
 
 
557
    if (share->db_create_options & HA_OPTION_PACK_KEYS)
 
558
      packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
 
559
    if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
 
560
      packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
 
561
    if (create_info.row_type != ROW_TYPE_DEFAULT)
 
562
    {
 
563
      packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
 
564
      packet->append(ha_row_type[(uint32_t) create_info.row_type]);
 
565
    }
 
566
    if (table->s->hasKeyBlockSize())
 
567
    {
 
568
      packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
 
569
      buff= to_string(table->s->getKeyBlockSize());
 
570
      packet->append(buff.c_str(), buff.length());
 
571
    }
 
572
    if (share->block_size)
 
573
    {
 
574
      packet->append(STRING_WITH_LEN(" BLOCK_SIZE="));
 
575
      buff= to_string(share->block_size);
 
576
      packet->append(buff.c_str(), buff.length());
 
577
    }
 
578
    table->cursor->append_create_info(packet);
 
579
    if (share->hasComment() && share->getCommentLength())
 
580
    {
 
581
      packet->append(STRING_WITH_LEN(" COMMENT="));
 
582
      append_unescaped(packet, share->getComment(),
 
583
                       share->getCommentLength());
 
584
    }
 
585
  }
 
586
  table->restore_column_map(old_map);
 
587
  return(0);
 
588
}
 
589
 
 
590
static void store_key_options(String *packet, Table *table, KEY *key_info)
 
591
{
 
592
  char *end, buff[32];
 
593
 
 
594
  if (key_info->algorithm == HA_KEY_ALG_BTREE)
 
595
    packet->append(STRING_WITH_LEN(" USING BTREE"));
 
596
 
 
597
  if (key_info->algorithm == HA_KEY_ALG_HASH)
 
598
    packet->append(STRING_WITH_LEN(" USING HASH"));
 
599
 
 
600
  if ((key_info->flags & HA_USES_BLOCK_SIZE) &&
 
601
      table->s->getKeyBlockSize() != key_info->block_size)
 
602
  {
 
603
    packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
 
604
    end= internal::int64_t10_to_str(key_info->block_size, buff, 10);
 
605
    packet->append(buff, (uint32_t) (end - buff));
 
606
  }
 
607
 
 
608
  assert(test(key_info->flags & HA_USES_COMMENT) ==
 
609
              (key_info->comment.length > 0));
 
610
  if (key_info->flags & HA_USES_COMMENT)
 
611
  {
 
612
    packet->append(STRING_WITH_LEN(" COMMENT "));
 
613
    append_unescaped(packet, key_info->comment.str,
 
614
                     key_info->comment.length);
 
615
  }
 
616
}
 
617
 
 
618
 
 
619
/****************************************************************************
 
620
  Return info about all processes
 
621
  returns for each thread: thread id, user, host, db, command, info
 
622
****************************************************************************/
 
623
 
 
624
class thread_info
 
625
{
 
626
  thread_info();
 
627
public:
 
628
  uint64_t thread_id;
 
629
  time_t start_time;
 
630
  uint32_t   command;
 
631
  string user;
 
632
  string host;
 
633
  string db;
 
634
  string proc_info;
 
635
  string state_info;
 
636
  string query;
 
637
  thread_info(uint64_t thread_id_arg,
 
638
              time_t start_time_arg,
 
639
              uint32_t command_arg,
 
640
              const string &user_arg,
 
641
              const string &host_arg,
 
642
              const string &db_arg,
 
643
              const string &proc_info_arg,
 
644
              const string &state_info_arg,
 
645
              const string &query_arg)
 
646
    : thread_id(thread_id_arg), start_time(start_time_arg), command(command_arg),
 
647
      user(user_arg), host(host_arg), db(db_arg), proc_info(proc_info_arg),
 
648
      state_info(state_info_arg), query(query_arg)
 
649
  {}
 
650
};
 
651
 
 
652
/*****************************************************************************
 
653
  Status functions
 
654
*****************************************************************************/
 
655
 
 
656
static vector<drizzle_show_var *> all_status_vars;
 
657
static vector<drizzle_show_var *> com_status_vars;
 
658
static bool status_vars_inited= 0;
 
659
static int show_var_cmp(const void *var1, const void *var2)
 
660
{
 
661
  return strcmp(((drizzle_show_var*)var1)->name, ((drizzle_show_var*)var2)->name);
 
662
}
 
663
 
 
664
class show_var_cmp_functor
 
665
{
 
666
  public:
 
667
  show_var_cmp_functor() { }
 
668
  inline bool operator()(const drizzle_show_var *var1, const drizzle_show_var *var2) const
 
669
  {
 
670
    int val= strcmp(var1->name, var2->name);
 
671
    return (val < 0);
 
672
  }
 
673
};
 
674
 
 
675
class show_var_remove_if
 
676
{
 
677
  public:
 
678
  show_var_remove_if() { }
 
679
  inline bool operator()(const drizzle_show_var *curr) const
 
680
  {
 
681
    return (curr->type == SHOW_UNDEF);
 
682
  }
 
683
};
 
684
 
 
685
drizzle_show_var *getFrontOfStatusVars()
 
686
{
 
687
  return all_status_vars.front();
 
688
}
 
689
 
 
690
drizzle_show_var *getCommandStatusVars()
 
691
{
 
692
  return com_status_vars.front();
 
693
}
 
694
 
 
695
/*
 
696
  Adds an array of drizzle_show_var entries to the output of SHOW STATUS
 
697
 
 
698
  SYNOPSIS
 
699
    add_status_vars(drizzle_show_var *list)
 
700
    list - an array of drizzle_show_var entries to add to all_status_vars
 
701
           the last entry must be {0,0,SHOW_UNDEF}
 
702
 
 
703
  NOTE
 
704
    The handling of all_status_vars[] is completely internal, it's allocated
 
705
    automatically when something is added to it, and deleted completely when
 
706
    the last entry is removed.
 
707
 
 
708
    As a special optimization, if add_status_vars() is called before
 
709
    init_status_vars(), it assumes "startup mode" - neither concurrent access
 
710
    to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
 
711
*/
 
712
int add_status_vars(drizzle_show_var *list)
 
713
{
 
714
  int res= 0;
 
715
  if (status_vars_inited)
 
716
    pthread_mutex_lock(&LOCK_status);
 
717
  while (list->name)
 
718
    all_status_vars.insert(all_status_vars.begin(), list++);
 
719
  if (status_vars_inited)
 
720
    sort(all_status_vars.begin(), all_status_vars.end(),
 
721
         show_var_cmp_functor());
 
722
  if (status_vars_inited)
 
723
    pthread_mutex_unlock(&LOCK_status);
 
724
  return res;
 
725
}
 
726
 
 
727
int add_com_status_vars(drizzle_show_var *list)
 
728
{
 
729
  int res= 0;
 
730
 
 
731
  while (list->name)
 
732
    com_status_vars.insert(com_status_vars.begin(), list++);
 
733
  if (status_vars_inited)
 
734
    sort(com_status_vars.begin(), com_status_vars.end(),
 
735
         show_var_cmp_functor());
 
736
 
 
737
  return res;
 
738
}
 
739
 
 
740
/*
 
741
  Make all_status_vars[] usable for SHOW STATUS
 
742
 
 
743
  NOTE
 
744
    See add_status_vars(). Before init_status_vars() call, add_status_vars()
 
745
    works in a special fast "startup" mode. Thus init_status_vars()
 
746
    should be called as late as possible but before enabling multi-threading.
 
747
*/
 
748
void init_status_vars()
 
749
{
 
750
  status_vars_inited= 1;
 
751
  sort(all_status_vars.begin(), all_status_vars.end(),
 
752
       show_var_cmp_functor());
 
753
  sort(com_status_vars.begin(), com_status_vars.end(),
 
754
       show_var_cmp_functor());
 
755
}
 
756
 
 
757
void reset_status_vars()
 
758
{
 
759
  vector<drizzle_show_var *>::iterator p;
 
760
 
 
761
  p= all_status_vars.begin();
 
762
  while (p != all_status_vars.end())
 
763
  {
 
764
    /* Note that SHOW_LONG_NOFLUSH variables are not reset */
 
765
    if ((*p)->type == SHOW_LONG)
 
766
      (*p)->value= 0;
 
767
    ++p;
 
768
  }
 
769
 
 
770
  p= com_status_vars.begin();
 
771
  while (p != com_status_vars.end())
 
772
  {
 
773
    /* Note that SHOW_LONG_NOFLUSH variables are not reset */
 
774
    if ((*p)->type == SHOW_LONG)
 
775
      (*p)->value= 0;
 
776
    ++p;
 
777
  }
 
778
}
 
779
 
 
780
/*
 
781
  catch-all cleanup function, cleans up everything no matter what
 
782
 
 
783
  DESCRIPTION
 
784
    This function is not strictly required if all add_to_status/
 
785
    remove_status_vars are properly paired, but it's a safety measure that
 
786
    deletes everything from the all_status_vars vector even if some
 
787
    remove_status_vars were forgotten
 
788
*/
 
789
void free_status_vars()
 
790
{
 
791
  all_status_vars.clear();
 
792
  com_status_vars.clear();
 
793
}
 
794
 
 
795
/*
 
796
  Removes an array of drizzle_show_var entries from the output of SHOW STATUS
 
797
 
 
798
  SYNOPSIS
 
799
    remove_status_vars(drizzle_show_var *list)
 
800
    list - an array of drizzle_show_var entries to remove to all_status_vars
 
801
           the last entry must be {0,0,SHOW_UNDEF}
 
802
 
 
803
  NOTE
 
804
    there's lots of room for optimizing this, especially in non-sorted mode,
 
805
    but nobody cares - it may be called only in case of failed plugin
 
806
    initialization in the mysqld startup.
 
807
*/
 
808
 
 
809
void remove_status_vars(drizzle_show_var *list)
 
810
{
 
811
  if (status_vars_inited)
 
812
  {
 
813
    pthread_mutex_lock(&LOCK_status);
 
814
    drizzle_show_var *all= all_status_vars.front();
 
815
    int a= 0, b= all_status_vars.size(), c= (a+b)/2;
 
816
 
 
817
    for (; list->name; list++)
 
818
    {
 
819
      int res= 0;
 
820
      for (a= 0, b= all_status_vars.size(); b-a > 1; c= (a+b)/2)
 
821
      {
 
822
        res= show_var_cmp(list, all+c);
 
823
        if (res < 0)
 
824
          b= c;
 
825
        else if (res > 0)
 
826
          a= c;
 
827
        else
 
828
          break;
 
829
      }
 
830
      if (res == 0)
 
831
        all[c].type= SHOW_UNDEF;
 
832
    }
 
833
    /* removes all the SHOW_UNDEF elements from the vector */
 
834
    all_status_vars.erase(std::remove_if(all_status_vars.begin(),
 
835
                            all_status_vars.end(),show_var_remove_if()),
 
836
                            all_status_vars.end());
 
837
    pthread_mutex_unlock(&LOCK_status);
 
838
  }
 
839
  else
 
840
  {
 
841
    drizzle_show_var *all= all_status_vars.front();
 
842
    uint32_t i;
 
843
    for (; list->name; list++)
 
844
    {
 
845
      for (i= 0; i < all_status_vars.size(); i++)
 
846
      {
 
847
        if (show_var_cmp(list, all+i))
 
848
          continue;
 
849
        all[i].type= SHOW_UNDEF;
 
850
        break;
 
851
      }
 
852
    }
 
853
    /* removes all the SHOW_UNDEF elements from the vector */
 
854
    all_status_vars.erase(std::remove_if(all_status_vars.begin(),
 
855
                            all_status_vars.end(),show_var_remove_if()),
 
856
                            all_status_vars.end());
 
857
  }
 
858
}
 
859
 
 
860
/* collect status for all running threads */
 
861
 
 
862
void calc_sum_of_all_status(system_status_var *to)
 
863
{
 
864
  /* Ensure that thread id not killed during loop */
 
865
  pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
 
866
 
 
867
  /* Get global values as base */
 
868
  *to= global_status_var;
 
869
 
 
870
  /* Add to this status from existing threads */
 
871
  for(SessionList::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
 
872
  {
 
873
    add_to_status(to, &((*it)->status_var));
 
874
  }
 
875
 
 
876
  pthread_mutex_unlock(&LOCK_thread_count);
 
877
  return;
 
878
}
 
879
 
146
880
} /* namespace drizzled */