~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/module/loader.cc

  • Committer: Andrew Hutchings
  • Date: 2010-12-08 07:35:23 UTC
  • mfrom: (1980 staging)
  • mto: This revision was merged to the branch mainline in revision 1981.
  • Revision ID: andrew@linuxjedi.co.uk-20101208073523-dokhzgnisocljo2k
Merge trunk into branch

Show diffs side-by-side

added added

removed removed

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