This patch fixes the example engine, the example parser, and the example daemon to compile. AKA You can now test that the interface is actually working :)
This commit is contained in:
parent
8a56fcff6a
commit
739f2c27d0
@ -2141,10 +2141,6 @@ MYSQL_CHECK_SSL
|
|||||||
# Has to be done late, as the plugin may need to check for existence of
|
# Has to be done late, as the plugin may need to check for existence of
|
||||||
# functions tested above
|
# functions tested above
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
MYSQL_PLUGIN(ftexample, [Simple Parser],
|
|
||||||
[Simple full-text parser plugin])
|
|
||||||
MYSQL_PLUGIN_DIRECTORY(ftexample, [plugin/fulltext])
|
|
||||||
MYSQL_PLUGIN_DYNAMIC(ftexample, [mypluglib.la])
|
|
||||||
|
|
||||||
MYSQL_STORAGE_ENGINE(partition, partition, [Partition Support],
|
MYSQL_STORAGE_ENGINE(partition, partition, [Partition Support],
|
||||||
[MySQL Partitioning Support], [max,max-no-ndb])
|
[MySQL Partitioning Support], [max,max-no-ndb])
|
||||||
|
@ -29,7 +29,8 @@
|
|||||||
#define MYSQL_UDF_PLUGIN 0 /* User-defined function */
|
#define MYSQL_UDF_PLUGIN 0 /* User-defined function */
|
||||||
#define MYSQL_STORAGE_ENGINE_PLUGIN 1 /* Storage Engine */
|
#define MYSQL_STORAGE_ENGINE_PLUGIN 1 /* Storage Engine */
|
||||||
#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */
|
#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */
|
||||||
#define MYSQL_MAX_PLUGIN_TYPE_NUM 3 /* The number of plugin types */
|
#define MYSQL_DAEMON_PLUGIN 3 /* The daemon/raw plugin type */
|
||||||
|
#define MYSQL_MAX_PLUGIN_TYPE_NUM 4 /* The number of plugin types */
|
||||||
|
|
||||||
/* We use the following strings to define licenses for plugins */
|
/* We use the following strings to define licenses for plugins */
|
||||||
#define PLUGIN_LICENSE_PROPRIETARY 0
|
#define PLUGIN_LICENSE_PROPRIETARY 0
|
||||||
@ -65,7 +66,7 @@ __MYSQL_DECLARE_PLUGIN(NAME, \
|
|||||||
builtin_ ## NAME ## _sizeof_struct_st_plugin, \
|
builtin_ ## NAME ## _sizeof_struct_st_plugin, \
|
||||||
builtin_ ## NAME ## _plugin)
|
builtin_ ## NAME ## _plugin)
|
||||||
|
|
||||||
#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0}}
|
#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0}}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
declarations for SHOW STATUS support in plugins
|
declarations for SHOW STATUS support in plugins
|
||||||
@ -295,6 +296,13 @@ struct st_mysql_ftparser
|
|||||||
int (*deinit)(MYSQL_FTPARSER_PARAM *param);
|
int (*deinit)(MYSQL_FTPARSER_PARAM *param);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
API for Storage Engine plugin. (MYSQL_DAEMON_PLUGIN)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* handlertons of different MySQL releases are incompatible */
|
||||||
|
#define MYSQL_DAEMON_INTERFACE_VERSION (MYSQL_VERSION_ID << 8)
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
API for Storage Engine plugin. (MYSQL_STORAGE_ENGINE_PLUGIN)
|
API for Storage Engine plugin. (MYSQL_STORAGE_ENGINE_PLUGIN)
|
||||||
*/
|
*/
|
||||||
@ -313,5 +321,15 @@ struct st_mysql_storage_engine
|
|||||||
int interface_version;
|
int interface_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Here we define only the descriptor structure, that is referred from
|
||||||
|
st_mysql_plugin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct st_mysql_daemon
|
||||||
|
{
|
||||||
|
int interface_version;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
1
plugin/daemon_example/AUTHORS
Normal file
1
plugin/daemon_example/AUTHORS
Normal file
@ -0,0 +1 @@
|
|||||||
|
Brian Aker <brian@mysql.com>
|
2
plugin/daemon_example/ChangeLog
Normal file
2
plugin/daemon_example/ChangeLog
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
0.1
|
||||||
|
- Added
|
21
plugin/daemon_example/Makefile.am
Normal file
21
plugin/daemon_example/Makefile.am
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#Makefile.am example for a daemon
|
||||||
|
MYSQLDATAdir = $(localstatedir)
|
||||||
|
MYSQLSHAREdir = $(pkgdatadir)
|
||||||
|
MYSQLBASEdir= $(prefix)
|
||||||
|
MYSQLLIBdir= $(pkglibdir)
|
||||||
|
INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
|
||||||
|
-I$(srcdir)
|
||||||
|
|
||||||
|
EXTRA_LTLIBRARIES = libdaemon_example.la
|
||||||
|
pkglib_LTLIBRARIES = @plugin_daemon_example_shared_target@
|
||||||
|
libdaemon_example_la_LDFLAGS = -module -rpath $(MYSQLLIBdir)
|
||||||
|
libdaemon_example_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
|
||||||
|
libdaemon_example_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
|
||||||
|
libdaemon_example_la_SOURCES = daemon_example.c
|
||||||
|
|
||||||
|
|
||||||
|
EXTRA_LIBRARIES = libdaemon_example.a
|
||||||
|
noinst_LIBRARIES = @plugin_daemon_example_static_target@
|
||||||
|
libdaemon_example_a_CXXFLAGS = $(AM_CFLAGS)
|
||||||
|
libdaemon_example_a_CFLAGS = $(AM_CFLAGS)
|
||||||
|
libdaemon_example_a_SOURCES= daemon_example.c
|
2
plugin/daemon_example/NEWS
Normal file
2
plugin/daemon_example/NEWS
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
0.1 - Tue Nov 7 12:08:03 PST 2006
|
||||||
|
* Added Example to test interface
|
8
plugin/daemon_example/README
Normal file
8
plugin/daemon_example/README
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Hi!
|
||||||
|
|
||||||
|
This is an example of a daemon plugin. These are generic plugins that
|
||||||
|
only hook ino the startup and shutdown of the database.
|
||||||
|
|
||||||
|
Cheers,
|
||||||
|
-Brian
|
||||||
|
Seattle, WA
|
9
plugin/daemon_example/configure.in
Normal file
9
plugin/daemon_example/configure.in
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# configure.in example for a daemon
|
||||||
|
|
||||||
|
AC_INIT(daemon_example, 0.1)
|
||||||
|
AM_INIT_AUTOMAKE
|
||||||
|
AC_DISABLE_STATIC
|
||||||
|
AC_PROG_LIBTOOL
|
||||||
|
AC_CONFIG_FILES([Makefile])
|
||||||
|
AC_OUTPUT
|
||||||
|
|
89
plugin/daemon_example/daemon_example.c
Normal file
89
plugin/daemon_example/daemon_example.c
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <mysql_version.h>
|
||||||
|
#include <mysql/plugin.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8)
|
||||||
|
#define __attribute__(A)
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initialize the daemon example at server start or plugin installation.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
daemon_example_plugin_init()
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Does nothing.
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
0 success
|
||||||
|
1 failure (cannot happen)
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int daemon_example_plugin_init(void *p)
|
||||||
|
{
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Terminate the daemon example at server shutdown or plugin deinstallation.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
daemon_example_plugin_deinit()
|
||||||
|
Does nothing.
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
0 success
|
||||||
|
1 failure (cannot happen)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int daemon_example_plugin_deinit(void *p)
|
||||||
|
{
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct st_mysql_daemon daemon_example_plugin=
|
||||||
|
{ MYSQL_DAEMON_INTERFACE_VERSION };
|
||||||
|
|
||||||
|
/*
|
||||||
|
Plugin library descriptor
|
||||||
|
*/
|
||||||
|
|
||||||
|
mysql_declare_plugin(daemon_example)
|
||||||
|
{
|
||||||
|
MYSQL_DAEMON_PLUGIN,
|
||||||
|
&daemon_example_plugin,
|
||||||
|
"daemon_example",
|
||||||
|
"Brian Aker",
|
||||||
|
"Daemon example that tests init and deinit of a plugin",
|
||||||
|
PLUGIN_LICENSE_GPL,
|
||||||
|
daemon_example_plugin_init, /* Plugin Init */
|
||||||
|
daemon_example_plugin_deinit, /* Plugin Deinit */
|
||||||
|
0x0100 /* 1.0 */,
|
||||||
|
NULL, /* status variables */
|
||||||
|
NULL, /* system variables */
|
||||||
|
NULL /* config options */
|
||||||
|
}
|
||||||
|
mysql_declare_plugin_end;
|
3
plugin/daemon_example/plug.in
Normal file
3
plugin/daemon_example/plug.in
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MYSQL_STORAGE_ENGINE(daemon_example,,[Daemon Example Plugin],
|
||||||
|
[This is an example plugin daemon.], [max,max-no-ndb])
|
||||||
|
MYSQL_PLUGIN_DYNAMIC(daemon_example, [libdaemon_example.la])
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
pkglibdir=$(libdir)/mysql
|
pkglibdir=$(libdir)/mysql
|
||||||
INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include
|
INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||||
noinst_LTLIBRARIES= mypluglib.la
|
#noinst_LTLIBRARIES= mypluglib.la
|
||||||
#pkglib_LTLIBRARIES= mypluglib.la
|
pkglib_LTLIBRARIES= mypluglib.la
|
||||||
mypluglib_la_SOURCES= plugin_example.c
|
mypluglib_la_SOURCES= plugin_example.c
|
||||||
mypluglib_la_LDFLAGS= -module -rpath $(pkglibdir)
|
mypluglib_la_LDFLAGS= -module -rpath $(pkglibdir)
|
||||||
mypluglib_la_CFLAGS= -DMYSQL_DYNAMIC_PLUGIN
|
mypluglib_la_CFLAGS= -DMYSQL_DYNAMIC_PLUGIN
|
||||||
|
3
plugin/fulltext/plug.in
Normal file
3
plugin/fulltext/plug.in
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MYSQL_PLUGIN(ftexample, [Simple Parser],
|
||||||
|
[Simple full-text parser plugin])
|
||||||
|
MYSQL_PLUGIN_DYNAMIC(ftexample, [mypluglib.la])
|
@ -62,7 +62,7 @@ static long number_of_calls= 0; /* for SHOW STATUS, see below */
|
|||||||
1 failure (cannot happen)
|
1 failure (cannot happen)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int simple_parser_plugin_init(void)
|
static int simple_parser_plugin_init(void *p)
|
||||||
{
|
{
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ static int simple_parser_plugin_init(void)
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int simple_parser_plugin_deinit(void)
|
static int simple_parser_plugin_deinit(void *p)
|
||||||
{
|
{
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
@ -6995,11 +6995,6 @@ static void mysql_init_variables(void)
|
|||||||
#else
|
#else
|
||||||
have_innodb= SHOW_OPTION_NO;
|
have_innodb= SHOW_OPTION_NO;
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_EXAMPLE_STORAGE_ENGINE
|
|
||||||
have_example_db= SHOW_OPTION_YES;
|
|
||||||
#else
|
|
||||||
have_example_db= SHOW_OPTION_NO;
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_ARCHIVE_STORAGE_ENGINE
|
#ifdef WITH_ARCHIVE_STORAGE_ENGINE
|
||||||
have_archive_db= SHOW_OPTION_YES;
|
have_archive_db= SHOW_OPTION_YES;
|
||||||
#else
|
#else
|
||||||
@ -8101,7 +8096,6 @@ void refresh_status(THD *thd)
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#undef have_innodb
|
#undef have_innodb
|
||||||
#undef have_ndbcluster
|
#undef have_ndbcluster
|
||||||
#undef have_example_db
|
|
||||||
#undef have_archive_db
|
#undef have_archive_db
|
||||||
#undef have_csv_db
|
#undef have_csv_db
|
||||||
#undef have_federated_db
|
#undef have_federated_db
|
||||||
@ -8111,7 +8105,6 @@ void refresh_status(THD *thd)
|
|||||||
|
|
||||||
SHOW_COMP_OPTION have_innodb= SHOW_OPTION_NO;
|
SHOW_COMP_OPTION have_innodb= SHOW_OPTION_NO;
|
||||||
SHOW_COMP_OPTION have_ndbcluster= SHOW_OPTION_NO;
|
SHOW_COMP_OPTION have_ndbcluster= SHOW_OPTION_NO;
|
||||||
SHOW_COMP_OPTION have_example_db= SHOW_OPTION_NO;
|
|
||||||
SHOW_COMP_OPTION have_archive_db= SHOW_OPTION_NO;
|
SHOW_COMP_OPTION have_archive_db= SHOW_OPTION_NO;
|
||||||
SHOW_COMP_OPTION have_csv_db= SHOW_OPTION_NO;
|
SHOW_COMP_OPTION have_csv_db= SHOW_OPTION_NO;
|
||||||
SHOW_COMP_OPTION have_federated_db= SHOW_OPTION_NO;
|
SHOW_COMP_OPTION have_federated_db= SHOW_OPTION_NO;
|
||||||
|
@ -667,8 +667,6 @@ sys_var_have_variable sys_have_compress("have_compress", &have_compress);
|
|||||||
sys_var_have_variable sys_have_crypt("have_crypt", &have_crypt);
|
sys_var_have_variable sys_have_crypt("have_crypt", &have_crypt);
|
||||||
sys_var_have_variable sys_have_csv_db("have_csv", &have_csv_db);
|
sys_var_have_variable sys_have_csv_db("have_csv", &have_csv_db);
|
||||||
sys_var_have_variable sys_have_dlopen("have_dynamic_loading", &have_dlopen);
|
sys_var_have_variable sys_have_dlopen("have_dynamic_loading", &have_dlopen);
|
||||||
sys_var_have_variable sys_have_example_db("have_example_engine",
|
|
||||||
&have_example_db);
|
|
||||||
sys_var_have_variable sys_have_federated_db("have_federated_engine",
|
sys_var_have_variable sys_have_federated_db("have_federated_engine",
|
||||||
&have_federated_db);
|
&have_federated_db);
|
||||||
sys_var_have_variable sys_have_geometry("have_geometry", &have_geometry);
|
sys_var_have_variable sys_have_geometry("have_geometry", &have_geometry);
|
||||||
@ -800,7 +798,6 @@ SHOW_VAR init_vars[]= {
|
|||||||
{sys_have_crypt.name, (char*) &have_crypt, SHOW_HAVE},
|
{sys_have_crypt.name, (char*) &have_crypt, SHOW_HAVE},
|
||||||
{sys_have_csv_db.name, (char*) &have_csv_db, SHOW_HAVE},
|
{sys_have_csv_db.name, (char*) &have_csv_db, SHOW_HAVE},
|
||||||
{sys_have_dlopen.name, (char*) &have_dlopen, SHOW_HAVE},
|
{sys_have_dlopen.name, (char*) &have_dlopen, SHOW_HAVE},
|
||||||
{sys_have_example_db.name, (char*) &have_example_db, SHOW_HAVE},
|
|
||||||
{sys_have_federated_db.name,(char*) &have_federated_db, SHOW_HAVE},
|
{sys_have_federated_db.name,(char*) &have_federated_db, SHOW_HAVE},
|
||||||
{sys_have_geometry.name, (char*) &have_geometry, SHOW_HAVE},
|
{sys_have_geometry.name, (char*) &have_geometry, SHOW_HAVE},
|
||||||
{sys_have_innodb.name, (char*) &have_innodb, SHOW_HAVE},
|
{sys_have_innodb.name, (char*) &have_innodb, SHOW_HAVE},
|
||||||
|
@ -23,21 +23,26 @@ extern struct st_mysql_plugin *mysqld_builtins[];
|
|||||||
|
|
||||||
char *opt_plugin_dir_ptr;
|
char *opt_plugin_dir_ptr;
|
||||||
char opt_plugin_dir[FN_REFLEN];
|
char opt_plugin_dir[FN_REFLEN];
|
||||||
|
/*
|
||||||
|
When you ad a new plugin type, add both a string and make sure that the
|
||||||
|
init and deinit array are correctly updated.
|
||||||
|
*/
|
||||||
const LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]=
|
const LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]=
|
||||||
{
|
{
|
||||||
{ C_STRING_WITH_LEN("UDF") },
|
{ C_STRING_WITH_LEN("UDF") },
|
||||||
{ C_STRING_WITH_LEN("STORAGE ENGINE") },
|
{ C_STRING_WITH_LEN("STORAGE ENGINE") },
|
||||||
{ C_STRING_WITH_LEN("FTPARSER") }
|
{ C_STRING_WITH_LEN("FTPARSER") },
|
||||||
|
{ C_STRING_WITH_LEN("DAEMON") }
|
||||||
};
|
};
|
||||||
|
|
||||||
plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
|
plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
|
||||||
{
|
{
|
||||||
0,ha_initialize_handlerton,0
|
0,ha_initialize_handlerton,0,0
|
||||||
};
|
};
|
||||||
|
|
||||||
plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
|
plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
|
||||||
{
|
{
|
||||||
0,ha_finalize_handlerton,0
|
0,ha_finalize_handlerton,0,0
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *plugin_interface_version_sym=
|
static const char *plugin_interface_version_sym=
|
||||||
@ -53,13 +58,15 @@ static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
|
|||||||
{
|
{
|
||||||
0x0000,
|
0x0000,
|
||||||
MYSQL_HANDLERTON_INTERFACE_VERSION,
|
MYSQL_HANDLERTON_INTERFACE_VERSION,
|
||||||
MYSQL_FTPARSER_INTERFACE_VERSION
|
MYSQL_FTPARSER_INTERFACE_VERSION,
|
||||||
|
MYSQL_DAEMON_INTERFACE_VERSION
|
||||||
};
|
};
|
||||||
static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
|
static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
|
||||||
{
|
{
|
||||||
0x0000, /* UDF: not implemented */
|
0x0000, /* UDF: not implemented */
|
||||||
MYSQL_HANDLERTON_INTERFACE_VERSION,
|
MYSQL_HANDLERTON_INTERFACE_VERSION,
|
||||||
MYSQL_FTPARSER_INTERFACE_VERSION
|
MYSQL_FTPARSER_INTERFACE_VERSION,
|
||||||
|
MYSQL_DAEMON_INTERFACE_VERSION
|
||||||
};
|
};
|
||||||
|
|
||||||
static DYNAMIC_ARRAY plugin_dl_array;
|
static DYNAMIC_ARRAY plugin_dl_array;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
MYSQL_STORAGE_ENGINE(example,, [Example Storage Engine],
|
MYSQL_STORAGE_ENGINE(example,, [Example Storage Engine],
|
||||||
[Skeleton for Storage Engines for developers], [max,max-no-ndb])
|
[Skeleton for Storage Engines for developers], [max,max-no-ndb])
|
||||||
MYSQL_PLUGIN_STATIC(example, [libexample.a])
|
|
||||||
MYSQL_PLUGIN_DYNAMIC(example, [ha_example.la])
|
MYSQL_PLUGIN_DYNAMIC(example, [ha_example.la])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user