~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/module/loader.cc

  • Committer: Brian Aker
  • Date: 2010-12-18 10:14:05 UTC
  • mfrom: (2008.1.3 clean)
  • Revision ID: brian@tangent.org-20101218101405-qjbse29shi9coklg
Merge of user identifier work

Show diffs side-by-side

added added

removed removed

Lines of Context:
47
47
#include "drizzled/pthread_globals.h"
48
48
#include "drizzled/util/tokenize.h"
49
49
 
 
50
#include <boost/foreach.hpp>
 
51
 
50
52
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
51
53
#ifndef RTLD_NOW
52
54
#define RTLD_NOW 1
73
75
{
74
76
 
75
77
 
76
 
class sys_var_pluginvar;
77
 
static vector<sys_var_pluginvar *> plugin_sysvar_vec;
78
 
 
79
78
typedef vector<string> PluginOptions;
80
79
static PluginOptions opt_plugin_load;
81
80
static PluginOptions opt_plugin_add;
128
127
static bookmark_unordered_map bookmark_hash;
129
128
 
130
129
 
131
 
/*
132
 
  sys_var class for access to all plugin variables visible to the user
133
 
*/
134
 
class sys_var_pluginvar: public sys_var
135
 
{
136
 
public:
137
 
  module::Module *plugin;
138
 
  drizzle_sys_var *plugin_var;
139
 
 
140
 
  sys_var_pluginvar(const std::string name_arg,
141
 
                    drizzle_sys_var *plugin_var_arg)
142
 
    :sys_var(name_arg), plugin_var(plugin_var_arg) {}
143
 
  sys_var_pluginvar *cast_pluginvar() { return this; }
144
 
  bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
145
 
  bool check_type(sql_var_t type)
146
 
  { return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
147
 
  bool check_update_type(Item_result type);
148
 
  SHOW_TYPE show_type();
149
 
  unsigned char* real_value_ptr(Session *session, sql_var_t type);
150
 
  TYPELIB* plugin_var_typelib(void);
151
 
  unsigned char* value_ptr(Session *session, sql_var_t type,
152
 
                           const LEX_STRING *base);
153
 
  bool check(Session *session, set_var *var);
154
 
  bool check_default(sql_var_t)
155
 
    { return is_readonly(); }
156
 
  void set_default(Session *session, sql_var_t);
157
 
  bool update(Session *session, set_var *var);
158
 
};
159
 
 
160
130
 
161
131
/* prototypes */
162
132
static void plugin_prune_list(vector<string> &plugin_list,
170
140
                               po::options_description &long_options);
171
141
static void unlock_variables(Session *session, drizzle_system_variables *vars);
172
142
static void cleanup_variables(drizzle_system_variables *vars);
173
 
static void plugin_vars_free_values(module::Module::Variables &vars);
174
143
 
175
144
/* declared in set_var.cc */
176
145
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
177
 
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
178
 
                                 const std::string &name, int64_t val);
179
 
 
180
 
static bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
181
 
                                 const char *name, int64_t val)
182
 
{
183
 
  const std::string name_str(name);
184
 
  return throw_bounds_warning(session, fixed, unsignd, name_str, val);
185
 
}
186
 
 
187
 
/****************************************************************************
188
 
  Value type thunks, allows the C world to play in the C++ world
189
 
****************************************************************************/
190
 
 
191
 
static int item_value_type(drizzle_value *value)
192
 
{
193
 
  switch (((st_item_value_holder*)value)->item->result_type()) {
194
 
  case INT_RESULT:
195
 
    return DRIZZLE_VALUE_TYPE_INT;
196
 
  case REAL_RESULT:
197
 
    return DRIZZLE_VALUE_TYPE_REAL;
198
 
  default:
199
 
    return DRIZZLE_VALUE_TYPE_STRING;
200
 
  }
201
 
}
202
 
 
203
 
static const char *item_val_str(drizzle_value *value,
204
 
                                char *buffer, int *length)
205
 
{
206
 
  String str(buffer, *length, system_charset_info), *res;
207
 
  if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
208
 
    return NULL;
209
 
  *length= res->length();
210
 
  if (res->c_ptr_quick() == buffer)
211
 
    return buffer;
212
 
 
213
 
  /*
214
 
    Lets be nice and create a temporary string since the
215
 
    buffer was too small
216
 
  */
217
 
  return current_session->strmake(res->c_ptr_quick(), res->length());
218
 
}
219
 
 
220
 
 
221
 
static int item_val_int(drizzle_value *value, int64_t *buf)
222
 
{
223
 
  Item *item= ((st_item_value_holder*)value)->item;
224
 
  *buf= item->val_int();
225
 
  if (item->is_null())
226
 
    return 1;
227
 
  return 0;
228
 
}
229
 
 
230
 
 
231
 
static int item_val_real(drizzle_value *value, double *buf)
232
 
{
233
 
  Item *item= ((st_item_value_holder*)value)->item;
234
 
  *buf= item->val_real();
235
 
  if (item->is_null())
236
 
    return 1;
237
 
  return 0;
238
 
}
239
146
 
240
147
 
241
148
/****************************************************************************
292
199
}
293
200
 
294
201
 
295
 
static void delete_module(module::Module *module)
296
 
{
297
 
  /* Free allocated strings before deleting the plugin. */
298
 
  plugin_vars_free_values(module->getSysVars());
299
 
  module->isInited= false;
300
 
  delete module;
301
 
}
302
 
 
303
 
 
304
202
static void reap_plugins(module::Registry &registry)
305
203
{
306
204
  std::map<std::string, module::Module *>::const_iterator modules=
309
207
  while (modules != registry.getModulesMap().end())
310
208
  {
311
209
    module::Module *module= (*modules).second;
312
 
    delete_module(module);
 
210
    delete module;
313
211
    ++modules;
314
212
  }
315
 
 
316
 
  drizzle_del_plugin_sysvar();
317
 
}
318
 
 
319
 
 
320
 
static void plugin_initialize_vars(module::Module *module)
321
 
{
322
 
  /*
323
 
    set the plugin attribute of plugin's sys vars so they are pointing
324
 
    to the active plugin
325
 
  */
326
 
  for (module::Module::Variables::iterator iter= module->getSysVars().begin();
327
 
       iter != module->getSysVars().end();
328
 
       ++iter)
329
 
  {
330
 
    sys_var *current_var= *iter;
331
 
    current_var->cast_pluginvar()->plugin= module;
332
 
  }
333
213
}
334
214
 
335
215
 
490
370
 
491
371
bool plugin_finalize(module::Registry &registry)
492
372
{
493
 
 
494
373
  /*
495
374
    Now we initialize all remaining plugins
496
375
  */
503
382
    ++modules;
504
383
    if (module->isInited == false)
505
384
    {
506
 
      plugin_initialize_vars(module);
507
 
 
508
385
      if (plugin_initialize(registry, module))
509
386
      {
510
387
        registry.remove(module);
511
 
        delete_module(module);
 
388
        delete module;
512
389
        return true;
513
390
      }
514
391
    }
515
392
  }
 
393
 
 
394
  BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
 
395
  {
 
396
    value.second->prime();
 
397
  }
 
398
 
516
399
  return false;
517
400
}
518
401
 
611
494
  global_variables_dynamic_size= 0;
612
495
}
613
496
 
614
 
/****************************************************************************
615
 
  Internal type declarations for variables support
616
 
****************************************************************************/
617
 
 
618
 
#undef DRIZZLE_SYSVAR_NAME
619
 
#define DRIZZLE_SYSVAR_NAME(name) name
620
 
#define PLUGIN_VAR_TYPEMASK 0x007f
621
 
 
622
 
static const uint32_t EXTRA_OPTIONS= 1; /* handle the NULL option */
623
 
 
624
 
typedef DECLARE_DRIZZLE_SYSVAR_BOOL(sysvar_bool_t);
625
 
typedef DECLARE_DRIZZLE_SessionVAR_BOOL(sessionvar_bool_t);
626
 
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
627
 
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
628
 
 
629
 
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
630
 
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
631
 
 
632
 
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
633
 
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
634
 
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
635
 
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
636
 
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
637
 
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
638
 
 
639
 
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
640
 
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
641
 
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
642
 
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
643
 
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
644
 
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
645
 
 
646
 
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
647
 
 
648
 
 
649
 
/****************************************************************************
650
 
  default variable data check and update functions
651
 
****************************************************************************/
652
 
 
653
 
static int check_func_bool(Session *, drizzle_sys_var *var,
654
 
                           void *save, drizzle_value *value)
655
 
{
656
 
  char buff[STRING_BUFFER_USUAL_SIZE];
657
 
  const char *strvalue= "NULL", *str;
658
 
  int result, length;
659
 
  int64_t tmp;
660
 
 
661
 
  if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
662
 
  {
663
 
    length= sizeof(buff);
664
 
    if (!(str= value->val_str(value, buff, &length)) ||
665
 
        (result= find_type(&bool_typelib, str, length, 1)-1) < 0)
666
 
    {
667
 
      if (str)
668
 
        strvalue= str;
669
 
      goto err;
670
 
    }
671
 
  }
672
 
  else
673
 
  {
674
 
    if (value->val_int(value, &tmp) < 0)
675
 
      goto err;
676
 
    if (tmp > 1)
677
 
    {
678
 
      internal::llstr(tmp, buff);
679
 
      strvalue= buff;
680
 
      goto err;
681
 
    }
682
 
    result= (int) tmp;
683
 
  }
684
 
  *(int*)save= -result;
685
 
  return 0;
686
 
err:
687
 
  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
688
 
  return 1;
689
 
}
690
 
 
691
 
 
692
 
static int check_func_int(Session *session, drizzle_sys_var *var,
693
 
                          void *save, drizzle_value *value)
694
 
{
695
 
  bool fixed;
696
 
  int64_t tmp;
697
 
  struct option options;
698
 
  value->val_int(value, &tmp);
699
 
  plugin_opt_set_limits(&options, var);
700
 
 
701
 
  if (var->flags & PLUGIN_VAR_UNSIGNED)
702
 
    *(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
703
 
                                                   &fixed);
704
 
  else
705
 
    *(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
706
 
 
707
 
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
708
 
                              var->name, (int64_t) tmp);
709
 
}
710
 
 
711
 
 
712
 
static int check_func_long(Session *session, drizzle_sys_var *var,
713
 
                          void *save, drizzle_value *value)
714
 
{
715
 
  bool fixed;
716
 
  int64_t tmp;
717
 
  struct option options;
718
 
  value->val_int(value, &tmp);
719
 
  plugin_opt_set_limits(&options, var);
720
 
 
721
 
  if (var->flags & PLUGIN_VAR_UNSIGNED)
722
 
    *(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
723
 
                                                   &fixed);
724
 
  else
725
 
    *(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
726
 
 
727
 
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
728
 
                              var->name, (int64_t) tmp);
729
 
}
730
 
 
731
 
 
732
 
static int check_func_int64_t(Session *session, drizzle_sys_var *var,
733
 
                               void *save, drizzle_value *value)
734
 
{
735
 
  bool fixed;
736
 
  int64_t tmp;
737
 
  struct option options;
738
 
  value->val_int(value, &tmp);
739
 
  plugin_opt_set_limits(&options, var);
740
 
 
741
 
  if (var->flags & PLUGIN_VAR_UNSIGNED)
742
 
    *(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
743
 
                                               &fixed);
744
 
  else
745
 
    *(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
746
 
 
747
 
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
748
 
                              var->name, (int64_t) tmp);
749
 
}
750
 
 
751
 
static int check_func_str(Session *session, drizzle_sys_var *,
752
 
                          void *save, drizzle_value *value)
753
 
{
754
 
  char buff[STRING_BUFFER_USUAL_SIZE];
755
 
  const char *str;
756
 
  int length;
757
 
 
758
 
  length= sizeof(buff);
759
 
  if ((str= value->val_str(value, buff, &length)))
760
 
    str= session->strmake(str, length);
761
 
  *(const char**)save= str;
762
 
  return 0;
763
 
}
764
 
 
765
 
 
766
 
static void update_func_bool(Session *, drizzle_sys_var *,
767
 
                             void *tgt, const void *save)
768
 
{
769
 
  *(bool *) tgt= *(int *) save ? 1 : 0;
770
 
}
771
 
 
772
 
 
773
 
static void update_func_int(Session *, drizzle_sys_var *,
774
 
                             void *tgt, const void *save)
775
 
{
776
 
  *(int *)tgt= *(int *) save;
777
 
}
778
 
 
779
 
 
780
 
static void update_func_long(Session *, drizzle_sys_var *,
781
 
                             void *tgt, const void *save)
782
 
{
783
 
  *(long *)tgt= *(long *) save;
784
 
}
785
 
 
786
 
 
787
 
static void update_func_int64_t(Session *, drizzle_sys_var *,
788
 
                                 void *tgt, const void *save)
789
 
{
790
 
  *(int64_t *)tgt= *(uint64_t *) save;
791
 
}
792
 
 
793
 
 
794
 
static void update_func_str(Session *, drizzle_sys_var *var,
795
 
                             void *tgt, const void *save)
796
 
{
797
 
  char *old= *(char **) tgt;
798
 
  *(char **)tgt= *(char **) save;
799
 
  if (var->flags & PLUGIN_VAR_MEMALLOC)
800
 
  {
801
 
    *(char **)tgt= strdup(*(char **) save);
802
 
    free(old);
803
 
    /*
804
 
     * There isn't a _really_ good thing to do here until this whole set_var
805
 
     * mess gets redesigned
806
 
     */
807
 
    if (tgt == NULL)
808
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
809
 
 
810
 
  }
811
 
}
812
 
 
813
497
 
814
498
/****************************************************************************
815
499
  System Variables support
816
500
****************************************************************************/
817
501
 
818
502
 
819
 
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
820
 
{
821
 
  sys_var *var;
822
 
  sys_var_pluginvar *pi= NULL;
823
 
  module::Module *module;
824
 
 
825
 
  if ((var= intern_find_sys_var(str, length, false)) &&
826
 
      (pi= var->cast_pluginvar()))
827
 
  {
828
 
    if (!(module= pi->plugin))
829
 
      var= NULL; /* failed to lock it, it must be uninstalling */
830
 
    else if (module->isInited == false)
831
 
    {
832
 
      var= NULL;
833
 
    }
834
 
  }
835
 
 
836
 
  /*
837
 
    If the variable exists but the plugin it is associated with is not ready
838
 
    then the intern_plugin_lock did not raise an error, so we do it here.
839
 
  */
840
 
  if (pi && !var)
841
 
  {
842
 
    my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
843
 
    assert(false);
844
 
  }
845
 
  return(var);
846
 
}
847
 
 
848
 
static const string make_bookmark_name(const string &plugin, const char *name)
849
 
{
850
 
  string varname(plugin);
851
 
  varname.push_back('_');
852
 
  varname.append(name);
853
 
 
854
 
  dashes_to_underscores(varname);
855
 
  return varname;
856
 
}
857
 
 
858
 
/*
859
 
  called by register_var, construct_options and test_plugin_options.
860
 
  Returns the 'bookmark' for the named variable.
861
 
  LOCK_system_variables_hash should be at least read locked
862
 
*/
863
 
static Bookmark *find_bookmark(const string &plugin, const char *name, int flags)
864
 
{
865
 
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
866
 
    return NULL;
867
 
 
868
 
  const string varname(make_bookmark_name(plugin, name));
869
 
 
870
 
  bookmark_unordered_map::iterator iter= bookmark_hash.find(varname);
871
 
  if (iter != bookmark_hash.end())
872
 
  {
873
 
    return &((*iter).second);
874
 
  }
875
 
  return NULL;
876
 
}
877
 
 
878
 
 
879
 
/*
880
 
  returns a bookmark for session-local variables, creating if neccessary.
881
 
  returns null for non session-local variables.
882
 
  Requires that a write lock is obtained on LOCK_system_variables_hash
883
 
*/
884
 
static Bookmark *register_var(const string &plugin, const char *name,
885
 
                                 int flags)
886
 
{
887
 
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
888
 
    return NULL;
889
 
 
890
 
  uint32_t size= 0, offset, new_size;
891
 
  Bookmark *result= NULL;
892
 
 
893
 
  switch (flags & PLUGIN_VAR_TYPEMASK) {
894
 
  case PLUGIN_VAR_BOOL:
895
 
    size= ALIGN_SIZE(sizeof(bool));
896
 
    break;
897
 
  case PLUGIN_VAR_INT:
898
 
    size= ALIGN_SIZE(sizeof(int));
899
 
    break;
900
 
  case PLUGIN_VAR_LONG:
901
 
    size= ALIGN_SIZE(sizeof(long));
902
 
    break;
903
 
  case PLUGIN_VAR_LONGLONG:
904
 
    size= ALIGN_SIZE(sizeof(uint64_t));
905
 
    break;
906
 
  case PLUGIN_VAR_STR:
907
 
    size= ALIGN_SIZE(sizeof(char*));
908
 
    break;
909
 
  default:
910
 
    assert(0);
911
 
    return NULL;
912
 
  };
913
 
 
914
 
 
915
 
  if (!(result= find_bookmark(plugin, name, flags)))
916
 
  {
917
 
    const string varname(make_bookmark_name(plugin, name));
918
 
 
919
 
    Bookmark new_bookmark;
920
 
    new_bookmark.key= varname;
921
 
    new_bookmark.offset= -1;
922
 
 
923
 
    assert(size && !(size & (size-1))); /* must be power of 2 */
924
 
 
925
 
    offset= global_system_variables.dynamic_variables_size;
926
 
    offset= (offset + size - 1) & ~(size - 1);
927
 
    new_bookmark.offset= (int) offset;
928
 
 
929
 
    new_size= (offset + size + 63) & ~63;
930
 
 
931
 
    if (new_size > global_variables_dynamic_size)
932
 
    {
933
 
      char* tmpptr= NULL;
934
 
      if (!(tmpptr=
935
 
              (char *)realloc(global_system_variables.dynamic_variables_ptr,
936
 
                              new_size)))
937
 
        return NULL;
938
 
      global_system_variables.dynamic_variables_ptr= tmpptr;
939
 
      tmpptr= NULL;
940
 
      if (!(tmpptr=
941
 
              (char *)realloc(max_system_variables.dynamic_variables_ptr,
942
 
                              new_size)))
943
 
        return NULL;
944
 
      max_system_variables.dynamic_variables_ptr= tmpptr;
945
 
           
946
 
      /*
947
 
        Clear the new variable value space. This is required for string
948
 
        variables. If their value is non-NULL, it must point to a valid
949
 
        string.
950
 
      */
951
 
      memset(global_system_variables.dynamic_variables_ptr +
952
 
             global_variables_dynamic_size, 0,
953
 
             new_size - global_variables_dynamic_size);
954
 
      memset(max_system_variables.dynamic_variables_ptr +
955
 
             global_variables_dynamic_size, 0,
956
 
             new_size - global_variables_dynamic_size);
957
 
      global_variables_dynamic_size= new_size;
958
 
    }
959
 
 
960
 
    global_system_variables.dynamic_variables_head= offset;
961
 
    max_system_variables.dynamic_variables_head= offset;
962
 
    global_system_variables.dynamic_variables_size= offset + size;
963
 
    max_system_variables.dynamic_variables_size= offset + size;
964
 
    global_system_variables.dynamic_variables_version++;
965
 
    max_system_variables.dynamic_variables_version++;
966
 
 
967
 
    new_bookmark.version= global_system_variables.dynamic_variables_version;
968
 
    new_bookmark.type_code= flags;
969
 
 
970
 
    /* this should succeed because we have already checked if a dup exists */
971
 
    bookmark_hash.insert(make_pair(varname, new_bookmark));
972
 
    result= find_bookmark(plugin, name, flags);
973
 
  }
974
 
  return result;
975
 
}
976
 
 
977
 
 
978
 
/*
979
 
  returns a pointer to the memory which holds the session-local variable or
980
 
  a pointer to the global variable if session==null.
981
 
  If required, will sync with global variables if the requested variable
982
 
  has not yet been allocated in the current thread.
983
 
*/
984
 
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
985
 
{
986
 
  assert(offset >= 0);
987
 
  assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
988
 
 
989
 
  if (!session)
990
 
    return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
991
 
 
992
 
  /*
993
 
    dynamic_variables_head points to the largest valid offset
994
 
  */
995
 
  if (!session->variables.dynamic_variables_ptr ||
996
 
      (uint32_t)offset > session->variables.dynamic_variables_head)
997
 
  {
998
 
    char *tmpptr= NULL;
999
 
    if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
1000
 
                                  global_variables_dynamic_size)))
1001
 
      return NULL;
1002
 
    session->variables.dynamic_variables_ptr= tmpptr;
1003
 
 
1004
 
    if (global_lock)
1005
 
      LOCK_global_system_variables.lock();
1006
 
 
1007
 
    //safe_mutex_assert_owner(&LOCK_global_system_variables);
1008
 
 
1009
 
    memcpy(session->variables.dynamic_variables_ptr +
1010
 
             session->variables.dynamic_variables_size,
1011
 
           global_system_variables.dynamic_variables_ptr +
1012
 
             session->variables.dynamic_variables_size,
1013
 
           global_system_variables.dynamic_variables_size -
1014
 
             session->variables.dynamic_variables_size);
1015
 
 
1016
 
    /*
1017
 
      now we need to iterate through any newly copied 'defaults'
1018
 
      and if it is a string type with MEMALLOC flag, we need to strdup
1019
 
    */
1020
 
    bookmark_unordered_map::iterator iter= bookmark_hash.begin();
1021
 
    for (; iter != bookmark_hash.end() ; ++iter)
1022
 
    {
1023
 
      sys_var_pluginvar *pi;
1024
 
      sys_var *var;
1025
 
      const Bookmark &v= (*iter).second;
1026
 
      const string var_name((*iter).first);
1027
 
 
1028
 
      if (v.version <= session->variables.dynamic_variables_version ||
1029
 
          !(var= intern_find_sys_var(var_name.c_str(), var_name.size(), true)) ||
1030
 
          !(pi= var->cast_pluginvar()) ||
1031
 
          v.type_code != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1032
 
        continue;
1033
 
 
1034
 
      /* Here we do anything special that may be required of the data types */
1035
 
 
1036
 
      if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1037
 
          pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1038
 
      {
1039
 
         char **pp= (char**) (session->variables.dynamic_variables_ptr +
1040
 
                             *(int*)(pi->plugin_var + 1));
1041
 
         if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1042
 
                             *(int*)(pi->plugin_var + 1))))
1043
 
           *pp= strdup(*pp);
1044
 
         if (*pp == NULL)
1045
 
           return NULL;
1046
 
      }
1047
 
    }
1048
 
 
1049
 
    if (global_lock)
1050
 
      LOCK_global_system_variables.unlock();
1051
 
 
1052
 
    session->variables.dynamic_variables_version=
1053
 
           global_system_variables.dynamic_variables_version;
1054
 
    session->variables.dynamic_variables_head=
1055
 
           global_system_variables.dynamic_variables_head;
1056
 
    session->variables.dynamic_variables_size=
1057
 
           global_system_variables.dynamic_variables_size;
1058
 
  }
1059
 
  return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1060
 
}
1061
 
 
1062
 
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1063
 
{
1064
 
  return (bool *)intern_sys_var_ptr(a_session, offset, true);
1065
 
}
1066
 
 
1067
 
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1068
 
{
1069
 
  return (int *)intern_sys_var_ptr(a_session, offset, true);
1070
 
}
1071
 
 
1072
 
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1073
 
{
1074
 
  return (long *)intern_sys_var_ptr(a_session, offset, true);
1075
 
}
1076
 
 
1077
 
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1078
 
{
1079
 
  return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1080
 
}
1081
 
 
1082
 
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1083
 
{
1084
 
  return (char **)intern_sys_var_ptr(a_session, offset, true);
1085
 
}
 
503
sys_var *find_sys_var(const char *str, uint32_t length)
 
504
{
 
505
  return intern_find_sys_var(str, length, false);
 
506
}
 
507
 
1086
508
 
1087
509
void plugin_sessionvar_init(Session *session)
1088
510
{
1134
556
}
1135
557
 
1136
558
 
1137
 
/**
1138
 
  @brief Free values of thread variables of a plugin.
1139
 
 
1140
 
  This must be called before a plugin is deleted. Otherwise its
1141
 
  variables are no longer accessible and the value space is lost. Note
1142
 
  that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1143
 
  must be freed.
1144
 
 
1145
 
  @param[in]        vars        Chain of system variables of a plugin
1146
 
*/
1147
 
 
1148
 
static void plugin_vars_free_values(module::Module::Variables &vars)
1149
 
{
1150
 
 
1151
 
  for (module::Module::Variables::iterator iter= vars.begin();
1152
 
       iter != vars.end();
1153
 
       ++iter)
1154
 
  {
1155
 
    sys_var_pluginvar *piv= (*iter)->cast_pluginvar();
1156
 
    if (piv &&
1157
 
        ((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
1158
 
        (piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
1159
 
    {
1160
 
      /* Free the string from global_system_variables. */
1161
 
      char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
1162
 
      free(*valptr);
1163
 
      *valptr= NULL;
1164
 
    }
1165
 
  }
1166
 
  return;
1167
 
}
1168
 
 
1169
 
 
1170
 
bool sys_var_pluginvar::check_update_type(Item_result type)
1171
 
{
1172
 
  if (is_readonly())
1173
 
    return 1;
1174
 
  switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1175
 
  case PLUGIN_VAR_INT:
1176
 
  case PLUGIN_VAR_LONG:
1177
 
  case PLUGIN_VAR_LONGLONG:
1178
 
    return type != INT_RESULT;
1179
 
  case PLUGIN_VAR_STR:
1180
 
    return type != STRING_RESULT;
1181
 
  default:
1182
 
    return 0;
1183
 
  }
1184
 
}
1185
 
 
1186
 
 
1187
 
SHOW_TYPE sys_var_pluginvar::show_type()
1188
 
{
1189
 
  switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1190
 
  case PLUGIN_VAR_BOOL:
1191
 
    return SHOW_MY_BOOL;
1192
 
  case PLUGIN_VAR_INT:
1193
 
    return SHOW_INT;
1194
 
  case PLUGIN_VAR_LONG:
1195
 
    return SHOW_LONG;
1196
 
  case PLUGIN_VAR_LONGLONG:
1197
 
    return SHOW_LONGLONG;
1198
 
  case PLUGIN_VAR_STR:
1199
 
    return SHOW_CHAR_PTR;
1200
 
  default:
1201
 
    assert(0);
1202
 
    return SHOW_UNDEF;
1203
 
  }
1204
 
}
1205
 
 
1206
 
 
1207
 
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, sql_var_t type)
1208
 
{
1209
 
  assert(session || (type == OPT_GLOBAL));
1210
 
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1211
 
  {
1212
 
    if (type == OPT_GLOBAL)
1213
 
      session= NULL;
1214
 
 
1215
 
    return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
1216
 
  }
1217
 
  return *(unsigned char**) (plugin_var+1);
1218
 
}
1219
 
 
1220
 
 
1221
 
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
1222
 
{
1223
 
  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
1224
 
  case PLUGIN_VAR_SessionLOCAL:
1225
 
    return ((sessionvar_enum_t *)plugin_var)->typelib;
1226
 
  default:
1227
 
    return NULL;
1228
 
  }
1229
 
  return NULL;
1230
 
}
1231
 
 
1232
 
 
1233
 
unsigned char* sys_var_pluginvar::value_ptr(Session *session, sql_var_t type, const LEX_STRING *)
1234
 
{
1235
 
  unsigned char* result;
1236
 
 
1237
 
  result= real_value_ptr(session, type);
1238
 
 
1239
 
  return result;
1240
 
}
1241
 
 
1242
 
 
1243
 
bool sys_var_pluginvar::check(Session *session, set_var *var)
1244
 
{
1245
 
  st_item_value_holder value;
1246
 
  assert(is_readonly() || plugin_var->check);
1247
 
 
1248
 
  value.value_type= item_value_type;
1249
 
  value.val_str= item_val_str;
1250
 
  value.val_int= item_val_int;
1251
 
  value.val_real= item_val_real;
1252
 
  value.item= var->value;
1253
 
 
1254
 
  return is_readonly() ||
1255
 
         plugin_var->check(session, plugin_var, &var->save_result, &value);
1256
 
}
1257
 
 
1258
 
 
1259
 
void sys_var_pluginvar::set_default(Session *session, sql_var_t type)
1260
 
{
1261
 
  const void *src;
1262
 
  void *tgt;
1263
 
 
1264
 
  assert(is_readonly() || plugin_var->update);
1265
 
 
1266
 
  if (is_readonly())
1267
 
    return;
1268
 
 
1269
 
  LOCK_global_system_variables.lock();
1270
 
  tgt= real_value_ptr(session, type);
1271
 
  src= ((void **) (plugin_var + 1) + 1);
1272
 
 
1273
 
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1274
 
  {
1275
 
    if (type != OPT_GLOBAL)
1276
 
      src= real_value_ptr(session, OPT_GLOBAL);
1277
 
    else
1278
 
    switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1279
 
        case PLUGIN_VAR_INT:
1280
 
          src= &((sessionvar_uint_t*) plugin_var)->def_val;
1281
 
          break;
1282
 
        case PLUGIN_VAR_LONG:
1283
 
          src= &((sessionvar_ulong_t*) plugin_var)->def_val;
1284
 
          break;
1285
 
        case PLUGIN_VAR_LONGLONG:
1286
 
          src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
1287
 
          break;
1288
 
        case PLUGIN_VAR_BOOL:
1289
 
          src= &((sessionvar_bool_t*) plugin_var)->def_val;
1290
 
          break;
1291
 
        case PLUGIN_VAR_STR:
1292
 
          src= &((sessionvar_str_t*) plugin_var)->def_val;
1293
 
          break;
1294
 
        default:
1295
 
          assert(0);
1296
 
        }
1297
 
  }
1298
 
 
1299
 
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1300
 
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1301
 
              session == current_session);
1302
 
 
1303
 
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
1304
 
  {
1305
 
    plugin_var->update(session, plugin_var, tgt, src);
1306
 
    LOCK_global_system_variables.unlock();
1307
 
  }
1308
 
  else
1309
 
  {
1310
 
    LOCK_global_system_variables.unlock();
1311
 
    plugin_var->update(session, plugin_var, tgt, src);
1312
 
  }
1313
 
}
1314
 
 
1315
 
 
1316
 
bool sys_var_pluginvar::update(Session *session, set_var *var)
1317
 
{
1318
 
  void *tgt;
1319
 
 
1320
 
  assert(is_readonly() || plugin_var->update);
1321
 
 
1322
 
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1323
 
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1324
 
              session == current_session);
1325
 
 
1326
 
  if (is_readonly())
1327
 
    return 1;
1328
 
 
1329
 
  LOCK_global_system_variables.lock();
1330
 
  tgt= real_value_ptr(session, var->type);
1331
 
 
1332
 
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
1333
 
  {
1334
 
    /* variable we are updating has global scope, so we unlock after updating */
1335
 
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
1336
 
    LOCK_global_system_variables.unlock();
1337
 
  }
1338
 
  else
1339
 
  {
1340
 
    LOCK_global_system_variables.unlock();
1341
 
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
1342
 
  }
1343
 
 return 0;
1344
 
}
1345
 
 
1346
 
 
1347
 
#define OPTION_SET_LIMITS(type, options, opt) \
1348
 
  options->var_type= type;                    \
1349
 
  options->def_value= (opt)->def_val;         \
1350
 
  options->min_value= (opt)->min_val;         \
1351
 
  options->max_value= (opt)->max_val;         \
1352
 
  options->block_size= (long) (opt)->blk_sz
1353
 
 
1354
 
 
1355
 
void plugin_opt_set_limits(struct option *options,
1356
 
                                                                                                         const drizzle_sys_var *opt)
1357
 
{
1358
 
  options->sub_size= 0;
1359
 
 
1360
 
  switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
1361
 
                        PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
1362
 
  /* global system variables */
1363
 
  case PLUGIN_VAR_INT:
1364
 
    OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
1365
 
    break;
1366
 
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
1367
 
    OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
1368
 
    break;
1369
 
  case PLUGIN_VAR_LONG:
1370
 
    OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
1371
 
    break;
1372
 
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
1373
 
    OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
1374
 
    break;
1375
 
  case PLUGIN_VAR_LONGLONG:
1376
 
    OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
1377
 
    break;
1378
 
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
1379
 
    OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
1380
 
    break;
1381
 
  case PLUGIN_VAR_BOOL:
1382
 
    options->var_type= GET_BOOL;
1383
 
    options->def_value= ((sysvar_bool_t*) opt)->def_val;
1384
 
    break;
1385
 
  case PLUGIN_VAR_STR:
1386
 
    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1387
 
                        GET_STR_ALLOC : GET_STR);
1388
 
    options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
1389
 
    break;
1390
 
  /* threadlocal variables */
1391
 
  case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
1392
 
    OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
1393
 
    break;
1394
 
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1395
 
    OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
1396
 
    break;
1397
 
  case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
1398
 
    OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
1399
 
    break;
1400
 
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1401
 
    OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
1402
 
    break;
1403
 
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
1404
 
    OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
1405
 
    break;
1406
 
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1407
 
    OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
1408
 
    break;
1409
 
  case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
1410
 
    options->var_type= GET_BOOL;
1411
 
    options->def_value= ((sessionvar_bool_t*) opt)->def_val;
1412
 
    break;
1413
 
  case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
1414
 
    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1415
 
                        GET_STR_ALLOC : GET_STR);
1416
 
    options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
1417
 
    break;
1418
 
  default:
1419
 
    assert(0);
1420
 
  }
1421
 
  options->arg_type= REQUIRED_ARG;
1422
 
  if (opt->flags & PLUGIN_VAR_NOCMDARG)
1423
 
    options->arg_type= NO_ARG;
1424
 
  if (opt->flags & PLUGIN_VAR_OPCMDARG)
1425
 
    options->arg_type= OPT_ARG;
1426
 
}
1427
 
 
1428
 
static int construct_options(memory::Root *mem_root, module::Module *tmp,
1429
 
                             option *options)
1430
 
{
1431
 
  
1432
 
  int localoptionid= 256;
1433
 
  const string plugin_name(tmp->getManifest().name);
1434
 
 
1435
 
  size_t namelen= plugin_name.size(), optnamelen;
1436
 
 
1437
 
  char *optname, *p;
1438
 
  int index= 0, offset= 0;
1439
 
  drizzle_sys_var *opt, **plugin_option;
1440
 
  Bookmark *v;
1441
 
 
1442
 
  string name(plugin_name);
1443
 
  transform(name.begin(), name.end(), name.begin(), ::tolower);
1444
 
 
1445
 
  underscores_to_dashes(name);
1446
 
 
1447
 
  /*
1448
 
    Two passes as the 2nd pass will take pointer addresses for use
1449
 
    by my_getopt and register_var() in the first pass uses realloc
1450
 
  */
1451
 
 
1452
 
  for (plugin_option= tmp->getManifest().system_vars;
1453
 
       plugin_option && *plugin_option; plugin_option++, index++)
1454
 
  {
1455
 
    opt= *plugin_option;
1456
 
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1457
 
      continue;
1458
 
    if (!(register_var(name, opt->name, opt->flags)))
1459
 
      continue;
1460
 
    switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
1461
 
    case PLUGIN_VAR_BOOL:
1462
 
      (((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
1463
 
      break;
1464
 
    case PLUGIN_VAR_INT:
1465
 
      (((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
1466
 
      break;
1467
 
    case PLUGIN_VAR_LONG:
1468
 
      (((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
1469
 
      break;
1470
 
    case PLUGIN_VAR_LONGLONG:
1471
 
      (((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
1472
 
      break;
1473
 
    case PLUGIN_VAR_STR:
1474
 
      (((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
1475
 
      break;
1476
 
    default:
1477
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1478
 
                      opt->flags, plugin_name.c_str());
1479
 
      return(-1);
1480
 
    };
1481
 
  }
1482
 
 
1483
 
  for (plugin_option= tmp->getManifest().system_vars;
1484
 
       plugin_option && *plugin_option; plugin_option++, index++)
1485
 
  {
1486
 
    switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
1487
 
    case PLUGIN_VAR_BOOL:
1488
 
      if (!opt->check)
1489
 
        opt->check= check_func_bool;
1490
 
      if (!opt->update)
1491
 
        opt->update= update_func_bool;
1492
 
      break;
1493
 
    case PLUGIN_VAR_INT:
1494
 
      if (!opt->check)
1495
 
        opt->check= check_func_int;
1496
 
      if (!opt->update)
1497
 
        opt->update= update_func_int;
1498
 
      break;
1499
 
    case PLUGIN_VAR_LONG:
1500
 
      if (!opt->check)
1501
 
        opt->check= check_func_long;
1502
 
      if (!opt->update)
1503
 
        opt->update= update_func_long;
1504
 
      break;
1505
 
    case PLUGIN_VAR_LONGLONG:
1506
 
      if (!opt->check)
1507
 
        opt->check= check_func_int64_t;
1508
 
      if (!opt->update)
1509
 
        opt->update= update_func_int64_t;
1510
 
      break;
1511
 
    case PLUGIN_VAR_STR:
1512
 
      if (!opt->check)
1513
 
        opt->check= check_func_str;
1514
 
      if (!opt->update)
1515
 
      {
1516
 
        opt->update= update_func_str;
1517
 
        if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
1518
 
        {
1519
 
          opt->flags|= PLUGIN_VAR_READONLY;
1520
 
          errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
1521
 
                            "to be read-only: string variable without "
1522
 
                            "update_func and PLUGIN_VAR_MEMALLOC flag"),
1523
 
                            opt->name, plugin_name.c_str());
1524
 
        }
1525
 
      }
1526
 
      break;
1527
 
    default:
1528
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1529
 
                      opt->flags, plugin_name.c_str());
1530
 
      return(-1);
1531
 
    }
1532
 
 
1533
 
    if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
1534
 
                    == PLUGIN_VAR_NOCMDOPT)
1535
 
      continue;
1536
 
 
1537
 
    if (!opt->name)
1538
 
    {
1539
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
1540
 
                    plugin_name.c_str());
1541
 
      return(-1);
1542
 
    }
1543
 
 
1544
 
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1545
 
    {
1546
 
      optnamelen= strlen(opt->name);
1547
 
      optname= (char*) mem_root->alloc_root(namelen + optnamelen + 2);
1548
 
      sprintf(optname, "%s-%s", name.c_str(), opt->name);
1549
 
      optnamelen= namelen + optnamelen + 1;
1550
 
    }
1551
 
    else
1552
 
    {
1553
 
      /* this should not fail because register_var should create entry */
1554
 
      if (!(v= find_bookmark(name, opt->name, opt->flags)))
1555
 
      {
1556
 
        errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
1557
 
                      "in plugin '%s'."), opt->name, plugin_name.c_str());
1558
 
        return(-1);
1559
 
      }
1560
 
 
1561
 
      *(int*)(opt + 1)= offset= v->offset;
1562
 
 
1563
 
      if (opt->flags & PLUGIN_VAR_NOCMDOPT)
1564
 
        continue;
1565
 
 
1566
 
      optname= (char*) mem_root->memdup_root(v->key.c_str(), (optnamelen= v->key.size()) + 1);
1567
 
    }
1568
 
 
1569
 
    /* convert '_' to '-' */
1570
 
    for (p= optname; *p; p++)
1571
 
      if (*p == '_')
1572
 
        *p= '-';
1573
 
 
1574
 
    options->name= optname;
1575
 
    options->comment= opt->comment;
1576
 
    options->app_type= opt;
1577
 
    options->id= localoptionid++;
1578
 
 
1579
 
    plugin_opt_set_limits(options, opt);
1580
 
 
1581
 
    if (opt->flags & PLUGIN_VAR_SessionLOCAL)
1582
 
      options->value= options->u_max_value= (char**)
1583
 
        (global_system_variables.dynamic_variables_ptr + offset);
1584
 
    else
1585
 
      options->value= options->u_max_value= *(char***) (opt + 1);
1586
 
 
1587
 
    options++;
1588
 
  }
1589
 
 
1590
 
  return(0);
1591
 
}
1592
 
 
1593
 
 
1594
 
static option *construct_help_options(memory::Root *mem_root, module::Module *p)
1595
 
{
1596
 
  drizzle_sys_var **opt;
1597
 
  option *opts;
1598
 
  uint32_t count= EXTRA_OPTIONS;
1599
 
 
1600
 
  for (opt= p->getManifest().system_vars; opt && *opt; opt++, count++) {};
1601
 
 
1602
 
  opts= (option*)mem_root->alloc_root((sizeof(option) * count));
1603
 
  if (opts == NULL)
1604
 
    return NULL;
1605
 
 
1606
 
  memset(opts, 0, sizeof(option) * count);
1607
 
 
1608
 
  if (construct_options(mem_root, p, opts))
1609
 
    return NULL;
1610
 
 
1611
 
  return(opts);
1612
 
}
1613
 
 
1614
 
void drizzle_add_plugin_sysvar(sys_var_pluginvar *var)
1615
 
{
1616
 
  plugin_sysvar_vec.push_back(var);
1617
 
}
1618
 
 
1619
 
void drizzle_del_plugin_sysvar()
1620
 
{
1621
 
  vector<sys_var_pluginvar *>::iterator iter= plugin_sysvar_vec.begin();
1622
 
  while(iter != plugin_sysvar_vec.end())
1623
 
  {
1624
 
    delete *iter;
1625
 
    ++iter;
1626
 
  }
1627
 
  plugin_sysvar_vec.clear();
1628
 
}
1629
559
 
1630
560
/*
1631
561
  SYNOPSIS
1638
568
  NOTE:
1639
569
    Requires that a write-lock is held on LOCK_system_variables_hash
1640
570
*/
1641
 
static int test_plugin_options(memory::Root *module_root,
 
571
static int test_plugin_options(memory::Root *,
1642
572
                               module::Module *test_module,
1643
573
                               po::options_description &long_options)
1644
574
{
1645
 
  drizzle_sys_var **opt;
1646
 
  option *opts= NULL;
1647
 
  int error;
1648
 
  drizzle_sys_var *o;
1649
 
  Bookmark *var;
1650
 
  uint32_t len, count= EXTRA_OPTIONS;
1651
575
 
1652
576
  if (test_module->getManifest().init_options != NULL)
1653
577
  {
1658
582
                                   module_options.add_options());
1659
583
    test_module->getManifest().init_options(opt_ctx);
1660
584
    long_options.add(module_options);
1661
 
 
1662
 
  }
1663
 
 
1664
 
  for (opt= test_module->getManifest().system_vars; opt && *opt; opt++)
1665
 
  {
1666
 
    count++;
1667
 
  }
1668
 
 
1669
 
  if (count > EXTRA_OPTIONS)
1670
 
  {
1671
 
    if (!(opts= (option*) module_root->alloc_root(sizeof(option) * count)))
1672
 
    {
1673
 
      errmsg_printf(ERRMSG_LVL_ERROR,
1674
 
                    _("Out of memory for plugin '%s'."),
1675
 
                    test_module->getName().c_str());
1676
 
      return(-1);
1677
 
    }
1678
 
    memset(opts, 0, sizeof(option) * count);
1679
 
 
1680
 
    if (construct_options(module_root, test_module, opts))
1681
 
    {
1682
 
      errmsg_printf(ERRMSG_LVL_ERROR,
1683
 
                    _("Bad options for plugin '%s'."),
1684
 
                    test_module->getName().c_str());
1685
 
      return(-1);
1686
 
    }
1687
 
 
1688
 
  }
1689
 
 
1690
 
  error= 1;
1691
 
 
1692
 
  {
1693
 
    for (opt= test_module->getManifest().system_vars; opt && *opt; opt++)
1694
 
    {
1695
 
      sys_var *v;
1696
 
      if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
1697
 
        continue;
1698
 
 
1699
 
      if ((var= find_bookmark(test_module->getName(), o->name, o->flags)))
1700
 
      {
1701
 
        v= new sys_var_pluginvar(var->key.c_str(), o);
1702
 
      }
1703
 
      else
1704
 
      {
1705
 
        len= test_module->getName().length() + strlen(o->name) + 2;
1706
 
        string vname(test_module->getName());
1707
 
        vname.push_back('-');
1708
 
        vname.append(o->name);
1709
 
        transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
1710
 
        dashes_to_underscores(vname);
1711
 
 
1712
 
        v= new sys_var_pluginvar(vname, o);
1713
 
      }
1714
 
      assert(v); /* check that an object was actually constructed */
1715
 
 
1716
 
      drizzle_add_plugin_sysvar(static_cast<sys_var_pluginvar *>(v));
1717
 
      try
1718
 
      {
1719
 
        add_sys_var_to_list(v);
1720
 
        test_module->addSysVar(v);
1721
 
      }
1722
 
      catch (...)
1723
 
      {
1724
 
        errmsg_printf(ERRMSG_LVL_ERROR,
1725
 
                      _("Plugin '%s' has conflicting system variables"),
1726
 
                      test_module->getName().c_str());
1727
 
        goto err;
1728
 
      }
1729
 
 
1730
 
    }
1731
 
 
1732
 
    return(0);
1733
 
  }
1734
 
 
1735
 
err:
1736
 
  if (opts)
1737
 
    my_cleanup_options(opts);
1738
 
  return(error);
 
585
  }
 
586
 
 
587
  return 0;
1739
588
}
1740
589
 
1741
590
 
1758
607
  module::Registry &registry= module::Registry::singleton();
1759
608
  vector<option> all_options;
1760
609
  memory::Root mem_root(4096);
1761
 
  option *opt= NULL;
1762
610
 
1763
611
 
1764
612
  if (initialized)
1776
624
      if (p->getManifest().init_options != NULL)
1777
625
        continue;
1778
626
 
1779
 
      if (p->getManifest().system_vars == NULL)
1780
 
        continue;
1781
 
 
1782
 
      opt= construct_help_options(&mem_root, p);
1783
 
      if (opt == NULL)
1784
 
        continue;
1785
 
 
1786
 
      /* Only options with a non-NULL comment are displayed in help text */
1787
 
      for (;opt->id; opt++)
1788
 
      {
1789
 
        if (opt->comment)
1790
 
        {
1791
 
          all_options.push_back(*opt);
1792
 
          
1793
 
        }
1794
 
      }
1795
627
    }
1796
628
  }
1797
629