~stewart/percona-playback/cassert-header

« back to all changes in this revision

Viewing changes to src/options.cc

  • Committer: Oleg Tsarev
  • Date: 2011-05-04 21:38:59 UTC
  • mfrom: (108.1.18 sbt)
  • Revision ID: oleg.tsarev@percona.com-20110504213859-pw1mgjmuj9gz44vb
merge split_by_transaction

Show diffs side-by-side

added added

removed removed

Lines of Context:
77
77
class Verbose_Callback_Fill : public Verbose_Callback
78
78
{
79
79
public:
80
 
  Verbose_Callback_Fill() : m_string_c_str(m_string.c_str()) {}
 
80
Verbose_Callback_Fill() : m_string_c_str(m_string.c_str()) {}
81
81
  virtual std::size_t operator()(char* buffer, std::size_t length, Query const &, Query_Result const &) const
82
82
  {
83
83
    return snprintf(buffer, length, m_string_c_str);
102
102
#define DECLARE_VERBOSE(name, printf_mask, verbose_mask, value, help_desc) \
103
103
  class Verbose_Callback_##name : public Verbose_Callback               \
104
104
  {                                                                     \
105
 
  public:                                                               \
 
105
public:                                                                 \
106
106
    Verbose_Callback_##name()                                           \
107
 
      {                                                                 \
108
 
        ::g_verbose_error |=                                            \
109
 
          (0 == strcmp( #name, "Error_Explain_Length" ))                \
110
 
          || (0 == strcmp( #name, "Error_Explain_Data"));               \
111
 
      }                                                                 \
 
107
    {                                                                   \
 
108
      ::g_verbose_error |=                                              \
 
109
        (0 == strcmp( #name, "Error_Explain_Length" ))                  \
 
110
        || (0 == strcmp( #name, "Error_Explain_Data"));                 \
 
111
    }                                                                   \
112
112
    static const char* mask()                                           \
113
113
    {                                                                   \
114
114
      return verbose_mask;                                              \
166
166
  s << "or use default presets: \n";
167
167
  s << "quiet - nothing\n";
168
168
  s << "status - %wt\\t%c\\t%a\\t%wm\\t%t\n";
169
 
  s << "error - %wt\\t%c\\t%a\\t%wm\\t%t\nerror length=%el data=%ed\n";
170
 
  s << "full - %wt\\t%c\\t%a\\t%wm\\t%t\nerror length=%el data=%ed\nquery length=%ql data=%qd\n";
 
169
  s << "error - %wt\\t%c\\t%a\\t%wm\\t%el\\t%ed\n";
 
170
  s << "full - %wt\\t%c\\t%a\\t%wm\\t%t\\t%el\\t%ed\\t%ql\\t%qd\n";
171
171
  return s.str();
172
172
}
173
173
 
182
182
void set_verbose(const char* mask)
183
183
{
184
184
  if (0 == strcmp(mask, "full"))
185
 
    {
186
 
      verbose_callback_variable= full_verbose_callback;
187
 
      g_verbose_error= true;
188
 
    }
 
185
  {
 
186
    verbose_callback_variable= full_verbose_callback;
 
187
    g_verbose_error= true;
 
188
  }
189
189
  else if (0 == strcmp(mask, "error"))
190
 
    {
191
 
      verbose_callback_variable= error_verbose_callback;
192
 
      g_verbose_error= true;
193
 
    }
 
190
  {
 
191
    verbose_callback_variable= error_verbose_callback;
 
192
    g_verbose_error= true;
 
193
  }
194
194
  else if (0 == strcmp(mask, "status"))
195
195
    verbose_callback_variable= status_verbose_callback;
196
196
  else if (0 == strcmp(mask, "quiet"))
197
197
    verbose_callback_variable= quiet_verbose_callback;
198
198
  else
 
199
  {
 
200
    verbose_callback_variable= &custom_verbose_callback;
 
201
    const char *mask_backup= mask;
 
202
    Verbose_Callback_Pointer fill(new Verbose_Callback_Fill());
 
203
    for (std::size_t length= strlen(mask); length > 0; --length, ++mask)
199
204
    {
200
 
      verbose_callback_variable= &custom_verbose_callback;
201
 
      const char *mask_backup= mask;
202
 
      Verbose_Callback_Pointer fill(new Verbose_Callback_Fill());
203
 
      for (std::size_t length= strlen(mask); length > 0; --length, ++mask)
204
 
        {
205
 
          if(*mask == '%')
206
 
            {
207
 
              const char *current_mask;
208
 
              std::size_t current_mask_length;
 
205
      if(*mask == '%')
 
206
      {
 
207
        const char *current_mask;
 
208
        std::size_t current_mask_length;
209
209
#define ADD(name)                                                       \
210
 
              current_mask= Verbose_Callback_##name::mask();            \
211
 
              current_mask_length= strlen(current_mask);                \
212
 
              if (length >= current_mask_length                         \
213
 
                  && 0 == strncmp(mask,                                 \
214
 
                                  current_mask,                         \
215
 
                                  current_mask_length))                 \
216
 
                {                                                       \
217
 
                  Verbose_Callback_Pointer current(new Verbose_Callback_##name()); \
218
 
                  custom_verbose_callback_vector.push_back(current);    \
219
 
                  mask += current_mask_length - 1;                      \
220
 
                  length -= current_mask_length - 1;                    \
221
 
                  continue;                                             \
222
 
                }
223
 
              ADD(Original_Thread);
224
 
              ADD(Work_Thread);
225
 
              ADD(Code);
226
 
              ADD(Affected_Rows);
227
 
              ADD(Original_Time);
228
 
              ADD(Work_Time);
229
 
              ADD(Query_Type);
230
 
              ADD(Error_Explain_Length);
231
 
              ADD(Error_Explain_Data);
232
 
              ADD(Query_Explain_Length);
233
 
              ADD(Query_Explain_Data);
 
210
        current_mask= Verbose_Callback_##name::mask();                  \
 
211
        current_mask_length= strlen(current_mask);                      \
 
212
        if (length >= current_mask_length                               \
 
213
            && 0 == strncmp(mask,                                       \
 
214
                            current_mask,                               \
 
215
                            current_mask_length))                       \
 
216
        {                                                               \
 
217
          Verbose_Callback_Pointer current(new Verbose_Callback_##name()); \
 
218
          custom_verbose_callback_vector.push_back(current);            \
 
219
          mask += current_mask_length - 1;                              \
 
220
          length -= current_mask_length - 1;                            \
 
221
          continue;                                                     \
 
222
        }
 
223
        ADD(Original_Thread);
 
224
        ADD(Work_Thread);
 
225
        ADD(Code);
 
226
        ADD(Affected_Rows);
 
227
        ADD(Original_Time);
 
228
        ADD(Work_Time);
 
229
        ADD(Query_Type);
 
230
        ADD(Error_Explain_Length);
 
231
        ADD(Error_Explain_Data);
 
232
        ADD(Query_Explain_Length);
 
233
        ADD(Query_Explain_Data);
234
234
#undef ADD
235
 
              std::ostringstream error;
236
 
              error << "Verbose mask '" <<  mask_backup << "' incorrect from " << (mask - mask_backup) << " symbol, fix please '" << mask << "'";
237
 
              throw Error(error.str());
238
 
            }
239
 
          else
240
 
            {
241
 
              Verbose_Callback_Fill *fill= 0;
242
 
              if (!custom_verbose_callback_vector.empty())
243
 
                {
244
 
                  fill= custom_verbose_callback_vector.back().get()->fill();
245
 
                }
246
 
              if (0 == fill)
247
 
                {
248
 
                  custom_verbose_callback_vector.push_back(Verbose_Callback_Pointer(new Verbose_Callback_Fill()));
249
 
                  fill= custom_verbose_callback_vector.back().get()->fill();
250
 
                }
251
 
              ASSERT(fill);
252
 
              fill->add(*mask);
253
 
            }
254
 
        }
 
235
        std::ostringstream error;
 
236
        error << "Verbose mask '" <<  mask_backup << "' incorrect from " << (mask - mask_backup) << " symbol, fix please '" << mask << "'";
 
237
        throw Error(error.str());
 
238
      }
 
239
      else
 
240
      {
 
241
        Verbose_Callback_Fill *fill= 0;
 
242
        if (!custom_verbose_callback_vector.empty())
 
243
        {
 
244
          fill= custom_verbose_callback_vector.back().get()->fill();
 
245
        }
 
246
        if (0 == fill)
 
247
        {
 
248
          custom_verbose_callback_vector.push_back(Verbose_Callback_Pointer(new Verbose_Callback_Fill()));
 
249
          fill= custom_verbose_callback_vector.back().get()->fill();
 
250
        }
 
251
        ASSERT(fill);
 
252
        fill->add(*mask);
 
253
      }
255
254
    }
 
255
  }
256
256
}
257
257
 
258
258
std::size_t verbose(char* buffer, std::size_t length, Query const &q, Query_Result const &r)
274
274
Too_Long_Argument::Too_Long_Argument(std::string const &argument_name
275
275
                                     , std::string const &limitation
276
276
                                     , std::string const &received) :
277
 
  Error(generate_message_Too_Long_Argument(argument_name, limitation, received))
278
 
  , m_name(argument_name)
 
277
Error(generate_message_Too_Long_Argument(argument_name, limitation, received))
 
278
, m_name(argument_name)
279
279
  , m_limitation(limitation)
280
280
  , m_received(received)
281
281
{
317
317
  return g_database;
318
318
}
319
319
 
 
320
const unsigned int g_port_max= 65536;
320
321
int g_port= 0;
321
322
int             port()
322
323
{
323
324
  return g_port;
324
325
}
325
326
 
 
327
const unsigned int g_worker_count_max= 1024;
 
328
unsigned int g_worker_count= 0;
 
329
unsigned int worker_count()
 
330
{
 
331
  return g_worker_count;
 
332
}
 
333
 
 
334
/*const unsigned int g_transaction_count_max= 1024;
 
335
unsigned int g_transaction_count= 0;
 
336
unsigned int transaction_count()
 
337
{
 
338
  return g_transaction_count;
 
339
  }*/
 
340
 
326
341
Socket g_socket;
327
342
Socket   const& socket()
328
343
{
357
372
    ("version", "version number")
358
373
    ("config",  po::value<std::string>(), "config")
359
374
    ("verbose,v", po::value<std::string>(), verbose_help_string.c_str())
360
 
    ("dry_run", "don't run queries on mysql (don't connect)");
 
375
    ("dry_run", "don't run queries on mysql (don't connect)")
 
376
    ("split_by_connection", "split queries by connection")
 
377
    ("split_by_transaction", "split queries by transaction")
 
378
    ("worker_count", po::value<unsigned int>()
 
379
     , "thread count [split_by_transation]");
 
380
  //("transaction_count", po::value<unsigned int>()
 
381
  //   , "transaction in queue count [split_by_transation]");
361
382
  po::options_description desc_mysql("MySQL client");
362
383
  desc_mysql.add_options()
363
384
    ("host",     po::value<std::string>(),  "mysql host")
373
394
  po::options_description desc("USAGE: ppb [General Options] [Input Source] [MySQ Options]");
374
395
  desc.add(desc_general).add(desc_mysql).add(desc_input);
375
396
  if (argc == 1)
376
 
    {
377
 
      std::cerr << desc << std::endl;
378
 
      exit(0);
379
 
    }
 
397
  {
 
398
    std::cerr << desc << std::endl;
 
399
    exit(0);
 
400
  }
380
401
  po::variables_map vm;
381
402
  po::store(po::parse_command_line(argc, argv, desc), vm);
382
403
  po::notify(vm);
383
404
 
384
405
  if (vm.count("help"))
385
 
    {
386
 
      std::cerr << desc << std::endl;
387
 
      exit(0);
388
 
    }
 
406
  {
 
407
    std::cerr << desc << std::endl;
 
408
    exit(0);
 
409
  }
389
410
  if (vm.count("version"))
390
 
    {
391
 
      std::cerr << "version: " << PERCONA_PLAYBACK_VERSION << std::endl;
392
 
      exit(0);
393
 
    }
 
411
  {
 
412
    std::cerr << "version: " << PERCONA_PLAYBACK_VERSION << std::endl;
 
413
    exit(0);
 
414
  }
394
415
  if (vm.count("config"))
395
 
    {
396
 
      std::ifstream config_file(vm["config"].as< std::string >().c_str());
397
 
      po::store(po::parse_config_file(config_file, desc), vm);
398
 
      notify(vm);
399
 
    }
 
416
  {
 
417
    std::ifstream config_file(vm["config"].as< std::string >().c_str());
 
418
    po::store(po::parse_config_file(config_file, desc), vm);
 
419
    notify(vm);
 
420
  }
400
421
  if (vm.count("verbose"))
401
 
    {
402
 
      std::string verbose_mask= vm[ "verbose" ].as<std::string>();
403
 
      set_verbose(verbose_mask.c_str());
404
 
    }
 
422
  {
 
423
    std::string verbose_mask= vm[ "verbose" ].as<std::string>();
 
424
    set_verbose(verbose_mask.c_str());
 
425
  }
405
426
  g_dry_run= vm.count("dry_run");
406
427
#define STRING(name)                                                    \
407
428
  if (vm.count( #name ))                                                \
408
 
    {                                                                   \
409
 
      std::string result= vm[ #name ].as<std::string>();                \
410
 
      if (result.length() > g_##name .max())                            \
411
 
        {                                                               \
412
 
          std::string limitation("maximum length is ");                 \
413
 
          limitation += boost::lexical_cast< std::string >(             \
414
 
                                                           g_##name .max() ); \
415
 
          throw Too_Long_Argument( #name                                \
416
 
                                   , limitation                         \
417
 
                                   , result);                           \
418
 
        }                                                               \
419
 
      g_##name .set(result);                                            \
420
 
    }
 
429
  {                                                                     \
 
430
    std::string result= vm[ #name ].as<std::string>();                  \
 
431
    if (result.length() > g_##name .max())                              \
 
432
    {                                                                   \
 
433
      std::string limitation("maximum length is ");                     \
 
434
      limitation += boost::lexical_cast< std::string >(                 \
 
435
                                                       g_##name .max() ); \
 
436
      throw Too_Long_Argument( #name                                    \
 
437
                               , limitation                             \
 
438
                               , result);                               \
 
439
    }                                                                   \
 
440
    g_##name .set(result);                                              \
 
441
  }
 
442
#define NUMBER(name)                                                    \
 
443
  if (vm.count( #name ))                                                \
 
444
  {                                                                     \
 
445
    g_##name = vm[ #name ].as<unsigned int>();                          \
 
446
    if ((unsigned int)g_##name > g_##name##_max)                        \
 
447
    {                                                                   \
 
448
      std::ostringstream max_string;                                    \
 
449
      max_string << "maximum value is " << g_##name##_max;              \
 
450
      std::ostringstream result_string;                                 \
 
451
      result_string << g_##name ;                                       \
 
452
      throw Too_Long_Argument(#name , max_string.str(), result_string.str()); \
 
453
    }                                                                   \
 
454
  }
421
455
  STRING(host);
422
456
  STRING(database);
423
457
  STRING(user);
424
458
  STRING(password);
425
 
  if (vm.count("port"))
426
 
    {
427
 
      g_port= vm["port"].as<unsigned int>();
428
 
      if (g_port > 65535)
429
 
        {
430
 
          std::ostringstream port_string;
431
 
          port_string << g_port;
432
 
          throw Too_Long_Argument("port", "maximum value is 66536", port_string.str());
433
 
        }
434
 
    }
 
459
  NUMBER(port);
 
460
  NUMBER(worker_count);
 
461
  //NUMBER(transaction_count);
 
462
  if (vm.count("split_by_transaction"))
 
463
  {
 
464
    if(vm.count("split_by_connection"))
 
465
    {
 
466
      throw Error("please choost just one: "
 
467
                  "split_by_connection"
 
468
                  ", "
 
469
                  "split_by_transction");
 
470
    }
 
471
    if (g_worker_count == 0)
 
472
    {
 
473
      throw Error("please choose not-zero worker_count");
 
474
    }
 
475
    /*if (g_transaction_count == 0)
 
476
    {
 
477
      throw Error("please choose not-zero transaction_count");
 
478
      }*/
 
479
  }
 
480
  else
 
481
  {
 
482
    if(vm.count("worker_count"))
 
483
    {
 
484
      throw Error("please use worker_count just for split_by_transction");
 
485
    }
 
486
    /*if(vm.count("transaction_count"))
 
487
    {
 
488
      throw Error("please use transaction_count just for split_by_transction");
 
489
      }*/
 
490
  }
435
491
  STRING(socket);
436
492
  STRING(slow_query_log_file);
437
493
  STRING(slow_query_log_socket);
441
497
  if (!slow_query_log_socket().is_null())
442
498
    source_count +=1 ;
443
499
  if (source_count > 1)
444
 
    {
445
 
      throw Error("Please select as input only one: file, socket");
446
 
    }
 
500
  {
 
501
    throw Error("Please select as input only one: file, socket");
 
502
  }
447
503
#undef STRING
448
504
}
449
505
 
450
 
MySQL_Options get_mysql_client_options(Thread_Id thread_id)
 
506
MySQL_Options get_mysql_client_options()
451
507
{
452
508
  MySQL_Options result;
453
 
  result.thread_id=    thread_id;
454
509
  result.host=         host();
455
510
  result.user=         user();
456
511
  result.password=     password();
460
515
  result.client_flags= 0;
461
516
  return result;
462
517
}
 
518
 
 
519
std::size_t max_idle_thread_count()
 
520
{
 
521
  return 100;
 
522
}