Вкратце

1. Вернулся из отпуска
2. Зашел отладчиком в исходный код fbclient.dll v3.0

facepalm

3. Захотелось пожелать разработчикам сервера всего доброго, хорошего настроения и здоровья

Большое тестирование #4

Слева диск «C» и справа диск «C» … И зачем мне два диска «C»?

Сегодня по-раздолбайству в задумчивости убил тестовый процесс, который работал уже седьмую неделю. Нажал не на ту кнопочку 🙂

Да черт с ней, с этой Голландией. Полтора месяца реальной работы — это тоже неплохо.

Тестовая машина та же, что и в прошлый раз — Q6600 / 8GB / выделенный массив 4x1TB WD RE4 в RAID0 на RS2BL040. Обновились только диски в рейде (были RE3).

Сервер: Firebird 2.5.6.26993 (x64, SuperClassic, модифицированный)
Провайдер: 3.29.0.20837 (x64)

Сервер и провайдер откомпилированы в VS2015 Upd2 (полная оптимизация).

Подключение к серверу через TCP/IP (localhost) и собственный клиент провайдера (то есть, без участия fbclient.dll).

Тесты запускались в 4 потока.

(далее…)

Вести с полей

Привет всем.

Вот так вот закопаешься в рутине и перестаешь осознавать — «что происходит и куда девается время?». Так что, хотя бы для себя лично, надо обозначить текущее состояние дел 🙂

1. Текущие триалы IBProvider-a уже поддерживают подключение к базам данных FB через собственного клиента с указанием версии IP-протокола в адресе базы данных: «inet4://» и «inet6://».

2. Медленно и печально перетряхиваю библиотеку libtommath, которую затащили в FB3 для использования SRP-аутентификации. Автор говорит — в 19 лет её накатал. Впечатляет, но для промышленного использования не пригодна.

3. Пошла шестая неделя большого тестирования — оно было запущено утром 17 апреля. Участники:

  • Firebird 2.5.6.26993 x64, SuperClassic, vc14 (полная оптимизация), модифицированный
  • IBProvider 3.29.0.20837 x64

Подключение: localhost, собственный клиент IBProvider-a для Firebird. Тесты выполняются в 4-е потока.

Точка предыдущего отказа еще не пройдена — количество тестов «немного» увеличилось. Пока полет нормальный. Но деградация производительности сервера уже на лице.

Пример пары тестов (вставка/удаление записей в одной транзакции), идентичных с точки зрения сервера:

Было:

[THR:005988] [05.05.2016 02:56:02] * START TEST [charsets.txt_params.enable_defer.user_trans.unicode.TBL_CS__UTF8.VARCHAR_ARRAY__32.cn_NONE.user_UTF8.chars_UTF8.param_adVarBinary_Array.bind_iunknown_array__std_ss.small.array_type_0]
[THR:005988] [05.05.2016 02:56:02] *
[THR:005988] [05.05.2016 02:56:02] * PREPARE
[THR:005988] [05.05.2016 02:56:02] * RUN
[THR:005988] [05.05.2016 02:56:02] [test] RelationName    :TBL_CS__UTF8
[THR:005988] [05.05.2016 02:56:02] [test] RelationField   :VARCHAR_ARRAY__32
[THR:005988] [05.05.2016 02:56:02] [test] UnicodeMode     :true
[THR:005988] [05.05.2016 02:56:02] [test] EnableDeferred  :true
[THR:005988] [05.05.2016 02:56:02] [test] AutoCommit      :false
[THR:005988] [05.05.2016 02:56:02] [test] CnCharset       :NONE
[THR:005988] [05.05.2016 02:56:02] [test] UserCharset     :UTF8
[THR:005988] [05.05.2016 02:56:02] [test] InParamType     :adArray+adVarBinary
[THR:005988] [05.05.2016 02:56:02] [test] InParamBindType :DBTYPE_IUNKNOWN | DBTYPE_ARRAY
[THR:005988] [05.05.2016 02:56:02] [test] OutParamType    :adArray+adVarBinary
[THR:005988] [05.05.2016 02:56:02] [test] OutParamBindType:DBTYPE_IUNKNOWN | DBTYPE_ARRAY
[THR:005988] [05.05.2016 02:56:02] [test] Prop_ArrayType  :0
[THR:005988] [05.05.2016 02:56:02] [test] Create connection...
[THR:005988] [05.05.2016 02:56:02] [test] create pooled data source...
[THR:005988] [05.05.2016 02:56:02] [test] set_init_prop: [array_type]=0
[THR:005988] [05.05.2016 02:56:02] [test] set_init_prop: [auto_commit]=false
[THR:005988] [05.05.2016 02:56:02] [test] set_init_prop: [ctype]=NONE
[THR:005988] [05.05.2016 02:56:02] [test] set_init_prop: [ctype_user]=UTF8
[THR:005988] [05.05.2016 02:56:02] [test] set_init_prop: [deferred_out_param]=3
[THR:005988] [05.05.2016 02:56:02] [test] set_init_prop: [unicode_mode]=true
[THR:005988] [05.05.2016 02:56:02] [test] connect to database ...OK
[THR:005988] [05.05.2016 02:56:02] [test] Create session...
[THR:005988] [05.05.2016 02:56:02] [test] START TRANSACTION ...
[THR:005988] [05.05.2016 02:56:02] [test] Create commands...
[THR:005988] [05.05.2016 02:56:02] [test] Prepare Command:

"insert into TBL_CS__UTF8 (VARCHAR_ARRAY__32) values (?) returning VARCHAR_ARRAY__32,test_id"

[THR:005988] [05.05.2016 02:56:02] [test] cmd.describe_params(param)
[THR:005988] [05.05.2016 02:56:02] [test] cmd.set_param_info(param)
[THR:005988] [05.05.2016 02:56:02] [test] Create command ...
[THR:005988] [05.05.2016 02:56:02] [test] Prepare Command:

"delete from TBL_CS__UTF8 where test_id=?"

[THR:005988] [05.05.2016 02:56:02] [test] cmd.describe_params(param)
[THR:005988] [05.05.2016 03:28:02] [test] Total pass number:524297
[THR:005988] [05.05.2016 03:28:02] [test] COMMIT TRANSACTION [RETAINING=false]...
[THR:005988] [05.05.2016 03:28:02] *
[THR:005988] [05.05.2016 03:28:02] * REAL   TIME:19203220000   [00:32:00.3220000]
[THR:005988] [05.05.2016 03:28:02] * USER   TIME:2506624068    [00:04:10.6624068]
[THR:005988] [05.05.2016 03:28:02] * KERNEL TIME:1080618927    [00:01:48.0618927]
[THR:005988] [05.05.2016 03:28:02] * TOTAL  TIME:3587242995    [00:05:58.7242995]
[THR:005988] [05.05.2016 03:28:02] *
[THR:005988] [05.05.2016 03:28:02] * STOP TEST [charsets.txt_params.enable_defer.user_trans.unicode.TBL_CS__UTF8.VARCHAR_ARRAY__32.cn_NONE.user_UTF8.chars_UTF8.param_adVarBinary_Array.bind_iunknown_array__std_ss.small.array_type_0]

Стало:

[THR:005980] [23.05.2016 06:06:10] * START TEST [charsets.txt_params.disable_defer.user_trans.unicode.TBL_CS__UTF8.VARCHAR_ARRAY__32.cn_NONE.user_UTF8.chars_UTF8.param_adVarBinary_Array.bind_iunknown_array__std_ss.small.array_type_0]
[THR:005980] [23.05.2016 06:06:10] *
[THR:005980] [23.05.2016 06:06:10] * PREPARE
[THR:005980] [23.05.2016 06:06:10] * RUN
[THR:005980] [23.05.2016 06:06:10] [test] RelationName    :TBL_CS__UTF8
[THR:005980] [23.05.2016 06:06:10] [test] RelationField   :VARCHAR_ARRAY__32
[THR:005980] [23.05.2016 06:06:10] [test] UnicodeMode     :true
[THR:005980] [23.05.2016 06:06:10] [test] EnableDeferred  :false
[THR:005980] [23.05.2016 06:06:10] [test] AutoCommit      :false
[THR:005980] [23.05.2016 06:06:10] [test] CnCharset       :NONE
[THR:005980] [23.05.2016 06:06:10] [test] UserCharset     :UTF8
[THR:005980] [23.05.2016 06:06:10] [test] InParamType     :adArray+adVarBinary
[THR:005980] [23.05.2016 06:06:10] [test] InParamBindType :DBTYPE_IUNKNOWN | DBTYPE_ARRAY
[THR:005980] [23.05.2016 06:06:10] [test] OutParamType    :adArray+adVarBinary
[THR:005980] [23.05.2016 06:06:10] [test] OutParamBindType:DBTYPE_IUNKNOWN | DBTYPE_ARRAY
[THR:005980] [23.05.2016 06:06:10] [test] Prop_ArrayType  :0
[THR:005980] [23.05.2016 06:06:10] [test] Create connection...
[THR:005980] [23.05.2016 06:06:10] [test] create pooled data source...
[THR:005980] [23.05.2016 06:06:10] [test] set_init_prop: [array_type]=0
[THR:005980] [23.05.2016 06:06:10] [test] set_init_prop: [auto_commit]=false
[THR:005980] [23.05.2016 06:06:10] [test] set_init_prop: [ctype]=NONE
[THR:005980] [23.05.2016 06:06:10] [test] set_init_prop: [ctype_user]=UTF8
[THR:005980] [23.05.2016 06:06:10] [test] set_init_prop: [deferred_out_param]=0
[THR:005980] [23.05.2016 06:06:10] [test] set_init_prop: [unicode_mode]=true
[THR:005980] [23.05.2016 06:06:10] [test] connect to database ...OK
[THR:005980] [23.05.2016 06:06:10] [test] Create session...
[THR:005980] [23.05.2016 06:06:10] [test] START TRANSACTION ...
[THR:005980] [23.05.2016 06:06:10] [test] Create commands...
[THR:005980] [23.05.2016 06:06:10] [test] Prepare Command:

"insert into TBL_CS__UTF8 (VARCHAR_ARRAY__32) values (?) returning VARCHAR_ARRAY__32,test_id"

[THR:005980] [23.05.2016 06:06:10] [test] cmd.describe_params(param)
[THR:005980] [23.05.2016 06:06:10] [test] cmd.set_param_info(param)
[THR:005980] [23.05.2016 06:06:10] [test] Create command ...
[THR:005980] [23.05.2016 06:06:10] [test] Prepare Command:

"delete from TBL_CS__UTF8 where test_id=?"

[THR:005980] [23.05.2016 06:06:11] [test] cmd.describe_params(param)
[THR:005980] [23.05.2016 07:13:22] [test] Total pass number:524297
[THR:005980] [23.05.2016 07:13:22] [test] COMMIT TRANSACTION [RETAINING=false]...
[THR:005980] [23.05.2016 07:13:22] *
[THR:005980] [23.05.2016 07:13:22] * REAL   TIME:40327720000   [01:07:12.7720000]
[THR:005980] [23.05.2016 07:13:22] * USER   TIME:2285570651    [00:03:48.5570651]
[THR:005980] [23.05.2016 07:13:22] * KERNEL TIME:966114193     [00:01:36.6114193]
[THR:005980] [23.05.2016 07:13:22] * TOTAL  TIME:3251684844    [00:05:25.1684844]

База опухла до 1TB.

Текущая статистика выглядит так:

Database "d:\Database\IBP_TEST_FB25_D3_2.GDB"
Database header page information:
        Flags                   0
        Checksum                12345
        Generation              42630329
        Page size               8192
        ODS version             11.2
        Oldest transaction      42477575
        Oldest active           42477576
        Oldest snapshot         42477572
        Next transaction        42477583
        Bumped transaction      1
        Sequence number         0
        Next attachment ID      137038
        Implementation ID       26
        Shadow count            0
        Page buffers            0
        Next header page        0
        Database dialect        3
        Creation date           Apr 16, 2016 21:08:36
        Attributes

    Variable header data:
        *END*

Новый триал IBProvider [сборка #20881]. Поддержка IPv6

Привет всем.

В новом триале, на уровне собственного клиента к Firebird, реализована поддержка IPv6. Так что, если у вас есть FB1-FB2.5 с поддержкой IPv6 — можете подключаться к нему через IBProvider 🙂

Была мысль добавить возможность указывать желаемый протокол через строку подключения — «inet4://localhost/…», «inet6://localhost/…», но решил пока не спешить. Кстати, аналогичная идея мелькала в FB-Devel.

В целом, это все связано с предварительной пробой пера в направлении создания собственного клиента к FB3.

Новый триал IBProvider [сборка #20828]

Привет всем.

Пару дней назад был выложен для тестирования новый триал IBProvider — v3.29.0.20828.

Главное и единственное изменение — при завершении (коммите/откате) транзакций, провайдер переводит связанные с ней курсоры и блобы в закрытое состояние.

Иными словами — провайдер наконец-то научился контролировать собственное состояние.

Вести с полей

Привет всем.

С начала года поменял пару жестких дисков — в ноуте (17410 часов) и десктопе (>40 тыс. часов).

Ноутбучный заменил на точно такой же — «Hitachi Travelstar 7K1000». В десктопе, после ротации, появился WD RE4 4TB — удивился, но мама выпуска 2007 года (x38, ICH9R) работает с ним без проблем.

А теперь Маша о главном. Что руки, что ноги… И тут начал помирать сервер, на котором последний год работал этот блог, сайт провайдера и еще много чего. Сейчас, благодаря героическим усилиям Администратора, идет процесс переезда на новое железо. Так что, если сайты в ближайшее время будут недоступны — звиняйте.

Сами понимаете — високосный год и все такое.

Обратная совместимость ISC API

Привет всем.

В процессе созерцания нового набора флагов IB12 (XE7) для XSQLVAR::sqlind

#define SQLIND_NULL         (short) (1 << 15)
#define SQLIND_INSERT       (1 << 0)
#define SQLIND_UPDATE       (1 << 1)
#define SQLIND_DELETE       (1 << 2)
#define SQLIND_CHANGE       (1 << 3)
#define SQLIND_CHANGE_VIEW  (1 << 5)

возникло две мысли:

1. Молодцы, что не боятся ломать существующий код. В предыдущих версиях sqlind принимал два значения: 0 и -1.

2. Вот почему бы не добавить возможность указания максимального «уровня» клиента? Если клиент не рюхает новые фишки, то и не надо разрешать их использовать.

Ну или явно разрешать подобные «фишки», которые клиент способен переварить.

Не знаю как лучше, но смысл, думаю, понятен.

В любом случае, полагаю, это нужно делать после подключения к базе данных, после определения типа и версии сервера.

XSQLVAR::sqltype и XSQLVAR::sqlind

Привет всем.

В ISC API, для представления описаний и значений колонок (параметров запроса), определена структура XSQLVAR.

typedef struct
{
 ISC_SHORT  sqltype;          /* datatype of field */
 ISC_SHORT  sqlscale;         /* scale factor */
 ISC_SHORT  sqlsubtype;       /* datatype subtype - currently BLOBs only */
 ISC_SHORT  sqllen;           /* length of data area */
 ISC_SCHAR* sqldata;          /* address of data */
 ISC_SHORT* sqlind;           /* address of indicator variable */
 ISC_SHORT  sqlname_length;   /* length of sqlname field */
 ISC_SCHAR  sqlname[32];      /* name of field, name length + space for NULL */
 ISC_SHORT  relname_length;   /* length of relation name */
 ISC_SCHAR  relname[32];      /* field's relation name + space for NULL */
 ISC_SHORT  ownname_length;   /* length of owner name */
 ISC_SCHAR  ownname[32];      /* relation's owner name + space for NULL */
 ISC_SHORT  aliasname_length; /* length of alias name */
 ISC_SCHAR  aliasname[32];    /* relation's alias name + space for NULL */
} XSQLVAR; 

Идентификатор типа указывается в поле XSQLVAR::sqltype и в случае NOT NULL колонки представляет собой четное число. Для Firebird 2.5 определен следующий набор идентификаторов типов данных:

#define SQL_TEXT         452
#define SQL_VARYING      448
#define SQL_SHORT        500
#define SQL_LONG         496
#define SQL_FLOAT        482
#define SQL_DOUBLE       480
#define SQL_D_FLOAT      530
#define SQL_TIMESTAMP    510
#define SQL_BLOB         520
#define SQL_ARRAY        540
#define SQL_QUAD         550
#define SQL_TYPE_TIME    560
#define SQL_TYPE_DATE    570
#define SQL_INT64        580
#define SQL_NULL       32766

В случае колонок, которые могут принимать значение NULL, к идентификатору типа данных добавляется единица.

Само значение индикатора NULL-состояние доступно по указателю XSQLVAR::sqlind. Минус один (-1) для NULL и ноль (0) для NOT NULL состояния.

Если идентификатор типа (XSQLVAR::sqltype) описывает обнуляемый тип, то XSQLVAR::sqlind должен содержать ненулевой указатель. Иначе возникнут проблемы.

Если идентификатор типа (XSQLVAR::sqltype) описывает NOT NULL колонку, то XSQLVAR::sqlind игнорируется.

Вот здесь мы подошли к вопросу, который регулярно появляется в моей голове, когда я вожусь с этим самым «XSQLVAR::sqlind»:

Какому гению пришло в голову увязывать наличие/отсутствие индикатора NULL-состояния (sqlind) значения с описанием типа (sqltype)?

Это же две несвязанные вещи!
(далее…)

Поддержка массивов в IBProvider

Привет всем.

На сайт выгружен новый триал IBProvider v3.28 с собственным механизмом чтения/записи массивов базы данных. Как я тут уже ранее писал — все это затеяно ради исправления бага с VARCHAR-массивами. Вкратце — клиент вместо VARCHAR-массивов должен был работать с CSTRING-массивами.

Исправление доступно только для серверов (FB/IB/YA), работающих на Windows (winnt_x86, winnt_amd64). Для остальных операционных систем и процессоров будет задействован старый добрый ISC API с одним ограничением — без поддержки чтения/записи VARCHAR-массивов.

Если есть пожелание добавить другие платформы — напишите, добавлю. Здесь только одна проблема — нужно будет прогнать тесты.

Настройка

По умолчанию, провайдер сам выбирает подходящий режим чтения/записи массивов с учетом платформы сервера и ODS базы данных.

Процессом выбора можно порулить с помощью нового свойства инициализации — «array_rw_mode». Допустимые значения: «api» или «direct».

Настройка распространяется на все колонки с массивами. Выборочная настройка для отдельных колонок не доступна.

Отмечу, что в случае IB7.1+ новый механизм нужно включать явно. По умолчанию, провайдер будет работать через ISC API. Это связано с шифрованием содержимого колонок, которое IBProvider, понятное дело, обеспечить не может.

Для FB (на Windows, x86/amd64), по умолчанию, будет использоваться новый механизм.

Это точно работает правильно?

Собственный механизм чтения/записи массивов был проверен практически на всех выпущенных версиях FB/IB. В том числе и с помощью перекрестных проверок.

Немного о внутренностях

Массивы в базе данных хранятся в блобах. Так что, новый механизм — это код, напрямую работающий с этими блобами.

Счастье наступило?

Лично для меня — да.

А в целом — нет. Потому что gbak работает через ISC API и, соответственно, он не сможет правильно сохранить и восстановить VARCHAR-массивы. Но это уже другая история.

«NEWS»: Firebird/Java Engine Plug-in in development

By fact, it is BREAKING NEWS!

facepalm
Adriano читает firebirdnews.org

PS. По моему, это как раз тот случай, когда надо сначала перепрыгнуть…