Вести с полей

Привет всем.

Никак не получается притормозить изменения в IBP и перейти к финализации версии 5.17. Ну очень увлекательное занятие.

0. Сначала о стороннем. Судя по субъективным наблюдениям — если гонять тесты в четыре потока, то FB3 (Win/SS/x64) вроде как работает без проблем. Если в десять потоков, то рано или поздно к нему приходит северный пушистый зверь и его приходится перегружать.

HOME4 Wed May 13 09:39:53 2020
Database: D:\DATABASE\RAM\IBP_TEST_FB30_D3.GDB
internal Firebird consistency check (pointer page vanished from DPM_next (249), file: dpm.cpp line: 1904)

При Обаме такого не было.

1. В IBP добавлена поддержка InterBase 2020 (v14). Поддержка заключается в определении нового списка ключевых слов и подключении исправленного механизма чтения/записи массивов. Последнее, по большому счету, заключается в прогоне тестов для 32-битного и 64-битного сервера.

Впечатление о сервере абсолютно нейтральное. Даже вспоминаться его родителей не хочется. Не упал и … ладно. Запросы типа «select EXTRACT(DAY FROM NULL) FROM …» как не переваривались, так и не перевариваются.

2. В схеме метаданных PROCEDURES корректно восстанавливается определение UDR процедур Firebird. Тут уже можно и выругаться по поводу отсутствия в дистрибутиве FB3 откомпилированного модуля udrcpp_example.dll. Типа, сами разбирайтесь …
(далее…)

64-битные счетчики ссылок

В новой тестовой сборке IBProvider (v5.17.0.34920) осуществлен переезд на 64-битные unsigned счетчики ссылок COM-объектов.

Как в 64-битных, так и в 32-битных сборках.

IUnknown::AddRef теперь всегда возвращает 1, а IUnknown::Release или 1 или 0.


Внутренние объекты тоже переведены на 64-битные счетчики ссылок.


Для инкремента и декремента используются Interlocked-функции Win32 API.

На древней 32-битной WinXP SP2 (в виртуальной машине) все работает.

Полагаю, проблемы будут только на древних системах с 32-битными процессорами.

Объектное API

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

1. В основе должен быть IUnknown.
— Это динамическая поддержка нескольких интерфейсов
— Это агрегация

1.5 Взять из COM принципы управления памятью и указателями на интерфейсы.

2. Первый аргумент методов должен быть указатель на интерфейс контекста вызова. Через этот контекст можно:
— Выполнять отмену вызова
— Возвращать описания ошибок/предупреждений/сообщений вызова
— Выделять память компоненту

Нужно ли передавать контекст в методы контекста? Наверное, да.

<уже начал напрягаться, чтобы вспомнить>

3. Для настройки и получения характеристик компонент следует использовать свойства, сгруппированные в наборы.

— Для идентификатора набора свойств вполне подходит GUID.
— Внутри набора используется целочисленный идентификатор свойства.
— У компоненты может быть несколько наборов свойств.
— У свойства может быть несколько равнозначных символьных идентификаторов.

— Свойство может связанно с несколькими объектами внутри компоненты (например — Columns внутри Rowset). При получении/установки свойства нужно указывать идентификатор целевого объекта.

4. Нужен аналог VARIANT. Для универсальной передачи типизированных значений (свойств, в первую очередь).

<пока все>


А, ну да. Напомню себе, что у модуля с компонентами должен быть метод инициализации и деинициализации. Допускается повторная инициализация, компенсируемая связанным вызовом метода деинициализации.


PS. Если вспомню что еще, дополню.

Вести с полей

В заканчивающимся апреле в IBProvider произошла пара сдвигов, которые планировались очень давно, но до них все никак «не доходили руки».

1. Получение плана запроса. Летом 2019-го один коварный клиент убедительно попросил добавить возможность получать через провайдер план запроса.

Я об этом думал уже давно. А тут еще и совесть начала про это напоминать. В общем, добавил.

Отмечу, что, благодаря этой небольшой задаче, завершена сборка новой пазлы для управления OLE DB свойствами — главой штуки пятой версии IBProvider.

2. Переезд на nullptr. Лет 10 назад, при переезде на VS2010, в библиотеку на C++ был добавлен псевдоним nullptr — structure::null_ptr. Он был нужен для обратной совместимости с VS2008.

С VS2008 я завязал достаточно давно. От VS2010 (и VS2012) я отказался год назад. С начала года, прекращена поддержка VS2013, VS2015. А structure::null_ptr продолжал жить и использоваться.

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

Так что, как сказано в одной популярной фильме — «Граждане, обратно дороги нет!»


Вообще, изменений, как обычно, прет очень много. Этот процесс напоминает покраску корабля, которая, как говорят сведущие люди, никогда не заканчивается…

4 года с момента релиза FB3

Subj

Я напомнил, а дальше вы сами 🙂

Вести с полей

В одной популярной книге по программированию для домохозяек советуют каждый день что-нибудь выкидывать из вещей. Этот ценный совет применим и для сопровождения программных систем.

Решил выкинуть из IBProvider сомнительный метод чтения с I4-колонок с приведением NULL к нулевому значению.

Он используется, в том числе, для чтения значения колонок rdb$procedure_inputs и rdb$procedure_outputs (таблица rdb$procedures).

Хотя бы из кода, работающего с базами данных FB3.

Тем более, что запрос

select * from rdb$procedures x
where x.rdb$procedure_inputs is null or x.rdb$procedure_outputs is null

для тестовой базы данных FB3 возвращает пустое множество.

Для тестовой базы IB4.2 (решил копнуть в начале огорода) этот запрос возвращает непустое множество. NULL-ы есть как в INPUTS так и в OUTPUTS.

С тестовой базой FB2.5.9 — ситуация аналогична IB4.2.

А у FB3 (повторюсь) — все OK.

Задумался, улыбнулся, сделал бакап базы FB2.5.9 и отресторил её на FB3.

Фух, все в норме 🙂

Вести с полей. C++17

Текущие тестовые сборки IBProvider (v5.14.0.33732) откомпилированы с указанием режима совместимости с C++17.

Пока в коде IBP ничего из C++17 не используется. Но вот STL таки да — уже из C++17.

Хотя нет. Я же «if constexpr» задействовал во встроенном zlib1, чтобы изничтожить часть предупреждений компилятора…

Из вещей, которые уже очень хочется начать использовать в самом IBProvider:

1. Сокращенное определение вложенных пространств имен

namespace ibp::db_client::remote_fb::api::p12{ .... }

вместо

namespace ibp{namespace db_client{namespace remote_fb{namespace api{namespace p12{ .... }}}}}

2. Fold expressions:

//Код из инсталлятора ADO.NET провайдера, который уже переехал на C++17.
template<typename... Args>
void BA_ErrorUtils::Throw__Error
               (HRESULT        const hr,
                BA_Error_SrcID const srcID,
                BA_Error_MsgID const errMsgCode,
                Args&&...            args)
{
 assert(FAILED(hr));

 BA_Error exc(hr,srcID,errMsgCode);

 (exc<<...<<std::forward<Args>(args));

 exc.raise();
}//Throw__Error

Но это все потом.

А пока — v5.14 это тот же v5.13.


Вышеобозначенные сборки (v5.14.0.33732) уже проехали через нагрузочное тестирование (которое сейчас работает как хорошо отрегулированный двигатель — без спотыканий).

Так что, думаю, на этой неделе они уйдут в релиз v5.14.

А может и нет — спешить не буду.

Нагрузочное тестирование IBP v5 (vc15)

Обычно, нагрузочное тестирование IBProvider выполняется с использованием сборок, созданных компилятором последней Visual Studio. В настоящий момент времени это VS2019 (сигнатура сборок — vc16).

В личных кабинетах доступны еще сборки, собранные в VS2017.

На днях один очень старый и любимый клиент продлил лицензию. И выбрал сборки VS2017 (сигнатура vc15).

Все бы ничего, но тут на rsdn проскочило сообщение о проблемах с VS2017.

Поэтому, во избежание неприятных неожиданностей, прогнал vc15-сборки последнего релиза IBProvider через нагрузочные тесты.

Все тип-топ.

Обновление инсталлятора ADO.NET провайдера

На сайт загружен обновленный инсталлятор ADO.NET провайдера, который самостоятельно может инсталлировать и деинсталлировать VSIX-пакеты с DDEX-провайдерами для VS2017/VS2019.

Так что, вот в эту инструкцию уже можно не вникать.

Как выглядят костыли в коде (#2)

Привет.

По свежим следам, добавлю сюда заметку про недавнее изменение в коде FB3.

Вдогонку

Вкратце о проблеме.

1. Есть объект со счетчиком ссылок (класс rem_port).
2. Этот объект управляется через смарт указатель. И, по идее, проблем быть не должно.
3. Тем не менее у него проблема с управлением времени жизни. Дважды удаляется в многопоточной среде.
4. Потому что конструктор rem_port, за каким-то …, вызывает addRef. И этот инкремент нужно где-то компенсировать однократным вызовом release.

Если я все правильно понял, багу заложили около 12 лет назад. Когда в rem_port добавили счетчик ссылок. Но это так, для ориентира.

Что делает этот патч. Он делает добавляет монопольность этого однократного вызова release.

	bool releasePort()
	{
		Firebird::RefMutexEnsureUnlock portGuard(*port_sync, FB_FUNCTION);
		const bool locked = portGuard.tryEnter();
		fb_assert(locked);

		fb_assert(!(port_flags & PORT_released));
		if (port_flags & PORT_released)
			return false;

		port_flags |= PORT_released;
		release();
		return true;
	}

При этом для блокировки он использует guard (*port_sync) и флаг (port_flags), которые находятся в самом защищаемом объекте.

Я считаю — это гениально.

Нет, правда, аплодирую стоя.