Архитектура на MySQL Нативен Драјвер за приклучоци
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
Архитектура на MySQL Нативен Драјвер за приклучоци
Референца за `mysqlnd.plugin.architecture.php` со подобрена типографија и навигација.
Архитектура на MySQL Нативен Драјвер за приклучоци
Овој дел дава преглед на mysqlnd
архитектурата на приклучоците.
Преглед на MySQL Native Driver
Пред да развиете mysqlnd приклучоци, корисно е да знаете малку за тоа како mysqlnd е организиран.
Mysqlnd се состои од следниве модули:
| Статистика на модули | mysqlnd_statistics.c |
|---|---|
| Конекција | mysqlnd.c |
| Резултат | mysqlnd_result.c |
| Метаподатоци за резултатот | mysqlnd_result_meta.c |
| Изјава | mysqlnd_ps.c |
| Memcached | mysqlnd_net.c |
| Протокол за жица | mysqlnd_wireprotocol.c |
ОО парадигма на C
На ниво на код, mysqlnd користи C шема за имплементирање на објектно ориентирање.
Во C користите struct за да претставувате објект. Членовите на структурата претставуваат својства на објектот. Членовите на структурата што покажуваат на функции претставуваат методи.
За разлика од други јазици како C++ или Java, не постојат фиксни правила за наследување во ОО парадигмата на C. Сепак, постојат некои конвенции што треба да се следат, а за кои ќе се дискутира подоцна.
PHP животен циклус
Кога се разгледува животниот циклус на PHP, постојат два основни циклуси:
- PHP циклус на стартување и исклучување на моторот
- Стартување и гаснење на PHP моторот
Циклус на барање
Кога PHP моторот ќе се стартува, ќе ја повика функцијата за иницијализација на модулот (MINIT) на секое регистрирано проширување. Ова му овозможува на секој модул да постави променливи и да распредели ресурси што ќе постојат за време на животниот век на процесот на PHP моторот. Кога PHP моторот ќе се исклучи, ќе ја повика функцијата за гаснење на модулот (MSHUTDOWN) на секое проширување.
За време на животниот век на PHP моторот, тој ќе прими голем број барања. Секое барање сочинува уште еден животен циклус. При секое барање, PHP моторот ќе ја повика функцијата за иницијализација на барањето на секое проширување. Проширувањето може да изврши какви било поставувања на променливи и распределба на ресурси потребни за обработка на барањето. Како што завршува циклусот на барање, моторот ја повикува функцијата за гаснење на барањето (RSHUTDOWN) на секое проширување, така што проширувањето може да изврши какво било чистење потребно.
А mysqlnd Како работи приклучокот mysqlnd приклучокот работи со пресретнување на повици направени до
mysqlndод проширувања што користат
mysqlnd . Ова се постигнува со добивање на
табела со функции, нејзино резервно копирање и замена со прилагодена табела со функции, која ги повикува функциите на приклучокот според потребите. mysqlnd Следниот код покажува како
/* a place to store original function table */
struct st_mysqlnd_conn_methods org_methods;
void minit_register_hooks(TSRMLS_D) {
/* active function table */
struct st_mysqlnd_conn_methods * current_methods
= mysqlnd_conn_get_methods();
/* backup original function table */
memcpy(&org_methods, current_methods,
sizeof(struct st_mysqlnd_conn_methods);
/* install new methods */
current_methods->query = MYSQLND_METHOD(my_conn_class, query);
}
се заменува табелата со функции:
Забелешка: Манипулациите со табелата со функции за поврзување мора да се направат за време на Иницијализација на модулот (MINIT). Табелата со функции е глобален заеднички ресурс. Во мулти-трејд околина, со TSRM градба, манипулацијата со глобален заеднички ресурс за време на обработката на барањето речиси сигурно ќе резултира со конфликти.
mysqlndНе користете никаква логика со фиксна големина при манипулирање со
табелата со функции: нови методи може да се додадат на крајот од табелата со функции. Табелата со функции може да се промени во секое време во иднина.
Повикување на родителски методи
Ако оригиналните записи во табелата со функции се резервно копирани, сè уште е можно да се повикаат оригиналните записи во табелата со функции - родителските методи.
Connection::stmt_init()Во некои случаи, како што е за
MYSQLND_METHOD(my_conn_class, query)(MYSQLND *conn,
const char *query, unsigned int query_len TSRMLS_DC) {
php_printf("my_conn_class::query(query = %s)\n", query);
query = "SELECT 'query rewritten' FROM DUAL";
query_len = strlen(query);
return org_methods.query(conn, query, query_len); /* return with call to parent */
}
, витално е да се повика родителскиот метод пред каква било друга активност во изведениот метод.
А mysqlnd Проширување на својства
mysqlnd објектите не можат едноставно да додаваат својства на објектите.
Произволни податоци (својства) може да се додадат на еден
mysqlnd објект користејќи соодветна функција од
mysqlnd_plugin_get_plugin_<object>_data()
семејството. При распределба на објект mysqlnd резервира простор на крајот од објектот за да задржи void *
покажувач до произволни податоци. mysqlnd резервира простор за еден void * покажувач по приклучок.
Следната табела покажува како да се пресмета позицијата на покажувачот за специфичен приклучок:
| Адреса на меморијата | Содржина |
|---|---|
| 0 | Почеток на C структурата на објектот mysqlnd |
| n | Крај на C структурата на објектот mysqlnd |
| void* до податоци на објектот на m-тиот приклучок | Ако планирате да ги наследите сите од |
конструкторите на објектот, што е дозволено, мора да го имате ова на ум! mysqlnd Следниот код покажува проширување на својствата:
Развивачот на приклучокот е одговорен за управувањето со меморијата на податоците на приклучокот.
/* any data we want to associate */
typedef struct my_conn_properties {
unsigned long query_counter;
} MY_CONN_PROPERTIES;
/* plugin id */
unsigned int my_plugin_id;
void minit_register_hooks(TSRMLS_D) {
/* obtain unique plugin ID */
my_plugin_id = mysqlnd_plugin_register();
/* snip - see Extending Connection: methods */
}
static MY_CONN_PROPERTIES** get_conn_properties(const MYSQLND *conn TSRMLS_DC) {
MY_CONN_PROPERTIES** props;
props = (MY_CONN_PROPERTIES**)mysqlnd_plugin_get_plugin_connection_data(
conn, my_plugin_id);
if (!props || !(*props)) {
*props = mnd_pecalloc(1, sizeof(MY_CONN_PROPERTIES), conn->persistent);
(*props)->query_counter = 0;
}
return props;
}
се препорачува мемориски распределувач за податоци на приклучокот. Овие функции се именувани користејќи конвенција:
Користењето на mysqlnd n + (m x sizeof(void*))
mnd_*loc()ќе треба да се прилагоди, и mysqlnd
алаторот има некои корисни карактеристики, како што е можноста да се користи алатор за отстранување грешки во склоп што не е за отстранување грешки.
| Кога да се подкласифицира? | Дали секоја инстанца има своја приватна табела со функции? | Како да се подкласифицира? | |
|---|---|---|---|
| Врска (MYSQLND) | MINIT | Овозможува пишување | mysqlnd_conn_get_methods() |
| Резултат (MYSQLND_RES) | MINIT или подоцна | Ограничено од | mysqlnd_result_get_methods() или манипулација со табелата со функции на методите на објектот |
| Мета податоци за резултат (MYSQLND_RES_METADATA) | MINIT | Овозможува пишување | mysqlnd_result_metadata_get_methods() |
| Изјава (MYSQLND_STMT) | MINIT | Овозможува пишување | mysqlnd_stmt_get_methods() |
| Мрежа (MYSQLND_NET) | MINIT или подоцна | Ограничено од | mysqlnd_net_get_methods() или манипулација со табелата со функции на методите на објектот |
| Протокол за жица (MYSQLND_PROTOCOL) | MINIT или подоцна | Ограничено од | mysqlnd_protocol_get_methods() или манипулација со табелата со функции на методите на објектот |
Не смеете да манипулирате со табелите со функции во кое било време по MINIT ако тоа не е дозволено според горната табела.
Некои класи содржат покажувач до табелата со функции на методите. Сите инстанци на таква класа ќе ја споделат истата табела со функции. За да се избегне хаос, особено во средини со повеќе нишки, таквите табели со функции мора да се манипулираат само за време на MINIT.
Други класи користат копии од глобално споделена табела со функции. Копијата на табелата со функции на класата се создава заедно со објектот. Секој објект користи своја табела со функции. Ова ви дава две опции: можете да ја манипулирате стандардната табела со функции на објект во MINIT, и можете дополнително да ги рафинирате методите на објект без да влијаете на други инстанци од истата класа.
Предноста на пристапот со споделена табела со функции е перформансот. Нема потреба да се копира табела со функции за секој објект.
| Тип | Алокација, конструкција, ресетирање | Може да се измени? | Повикувач |
|---|---|---|---|
| Врска (MYSQLND) | mysqlnd_init() | Овозможува пишување | mysqlnd_connect() |
| Резултатсет(MYSQLND_RES) |
Алокација:
|
Да, но повикај родител! |
|
| Мета податоци за резултат (MYSQLND_RES_METADATA) | Connection::result_meta_init() | Да, но повикај родител! | Result::read_result_metadata() |
| Изјава (MYSQLND_STMT) | Connection::stmt_init() | Да, но повикај родител! | Connection::stmt_init() |
| Мрежа (MYSQLND_NET) | mysqlnd_net_init() | Овозможува пишување | Connection::init() |
| Протокол за жица (MYSQLND_PROTOCOL) | mysqlnd_protocol_init() | Овозможува пишување | Connection::init() |
Силно се препорачува да не го заменувате конструкторот во целост. Конструкторите вршат алокации на меморија. Алокациите на меморија се клучни за mysqlnd plugin API и логиката на објектот на mysqlnd. Ако не ви се грижите за предупредувањата и инсистирате на закачување на конструкторите, треба барем да го повикате родителскиот конструктор пред да направите било што во вашиот конструктор.
Без оглед на сите предупредувања, може да биде корисно да се наследат конструктори. Конструкторите се совршено место за модифицирање на табелите со функции на објекти со несподелени табели со објекти, како што се Resultset, Network, Wire Protocol.
| Тип | Изведениот метод мора да го повика родителот? | клучниот збор се преведува во името на класата во која се наоѓа кодот. Во овој случај, |
|---|---|---|
| Конекција | да, по извршувањето на методот | free_contents(), end_psession() |
| Резултат | да, по извршувањето на методот | free_result() |
| Метаподатоци од резултат | да, по извршувањето на методот | free() |
| Изјава | да, по извршувањето на методот | dtor(), free_stmt_content() |
| Memcached | да, по извршувањето на методот | free() |
| Протокол за жица | да, по извршувањето на методот | free() |
Деструкторите се соодветно место за ослободување на својствата,
mysqlnd_plugin_get_plugin_<object>_data().
Наведените деструктори можеби не се еквивалентни на вистинските
mysqlnd метод што го ослободува самиот објект. Сепак, тие се најдоброто можно место за вас да се вклучите и да ги ослободите податоците на вашиот приклучок. Како и со конструкторите, можете да ги замените методите целосно, но ова не се препорачува. Ако се наведени повеќе методи во горната табела, ќе треба да ги вклучите сите наведени методи и да ги ослободите податоците на вашиот приклучок во кој било од методите што ќе биде повикан прв од
mysqlnd.
Препорачаниот метод за приклучоци е едноставно да се вклучат методите, да се ослободи меморијата и веднаш да се повика имплементацијата на родителот по ова.