Вести с полей. 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), которые находятся в самом защищаемом объекте.

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

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

… и в продакшн

%subj% был первой мыслью с утра.

Да, походу оно как-то так у нормальных людей и организовано 🙂

[winsock][BUG CHECK] Чтение из закрытого порта подключения. Ошибка WinSock: 0

Вчера замутил инструкцию по загрузке данных из FireBird в Excel.

Многократно нарывался на %subj%.

Проблему давил OK-еем. Она не сильно мешала достижения финиша.

Позже сообразил, что она уже вылазила. Причем совсем недавно.

В том случае, проблема лечилась указанием имени пользователя в верхнем регистре (GAMER) — это (насколько я понимаю) задействовало SRP-аутентификацию. А с нижним регистром через раз отрабатывала Legacy_Auth аутентификация.

Но вчера SYSDBA был в верхнем регистре!
(далее…)

IBProvider v5.12 и NetProvider v1.16

На сайт и в личные кабинеты загружены очередные обновления OLE DB и ADO.NET провайдеров.

IBProvider v5.12
В IBProvider, как я тут раньше писал, появилась поддержка колонок с автоинкрементом.

А если конкретнее, то во множестве с описанием колонок, получаемом через интерфейс IColumnsRowset, появилась колонка DBCOLUMN_ISAUTOINCREMENT с BOOL-значением. В ней будет True для колонок с автоинкрементом и False для всех остальных колонок.

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

На финише, в IBProvider было внесено еще одно изменение — отображение ошибки Z_MEM_ERROR компрессора данных zlib1 на E_OUTOFMEMORY.

Основные сборки (vc16), как положено, прошли через многопоточное нагрузочное тестирование.

NetProvider v1.16
В OleDbDataReader, создаваемом с указанием CommandBehavior.SchemaOnly, разрешено использование методов Read, HasRows, RecordsAffected.

Предыдущие сборки провайдера запрещали такие вызовы и выкидывали исключение.

Клиент, в процессе переезда с System.Data.OleDb, обнаружил это лютое ограничение и попросил убрать его.

Другое
Доработаны и оптимизированы тесты. Причем для обоих провайдеров. Новые тестовые таблички (в которых по 4K колонок) дали всем прикурить.

Из личных кабинетов убраны сборки IBProvider v3. Все, эпоха закончилась.

Лучше день потерять…

…потом за пять минут долететь.

В рамках тестирования следующей версии IBProvider v5.12 была создана пара UBER таблиц c 4096-ю колонок в каждой, которые добили прямолинейные алгоритмы тестирования схем метаданных «schema.002.*» основной тестовой системы.

Их там три штуки. Тот, который грузит схемы без кэширования, до последнего времени работал 6 часов. После появления вышеобозначенной сладкой парочки — 2 дня и 19 часов. То есть 67 часов.

Это означает, что после завершения всех остальных тестов, компьютер еще кучу времени тупил в одно ядро над одним тестом. 9 ядер простаивали.

Страшно думать, сколько бы оно тупило с отладочной сборкой провайдера. Сто пудов — не меньше недели … (далее…)

Вести с полей

Утром выложил новую тестовую сборку провайдера (3.12.0.33717) с поддержкой IDENTITY колонок FB3.

Не прошло… хотя нет, таки прошло, шесть лет как я это сделал.

Ну, думаю, надо бы теперь соорудить примерчик на .NET, который бы показал «как узнать — имеет колонка автоинкремент или нет?».

Накатал.

////////////////////////////////////////////////////////////////////////////////
//Samples for LCPI ADO.NET Data provider for OLEDB.
//                                                    ibprovider.com. 16.12.2020
using System;
using lcpi.data.oledb;

using structure_lib=lcpi.lib.structure;

namespace Sample_0028{
////////////////////////////////////////////////////////////////////////////////
//class Program

class Program
{
 private const string c_cn_str
  ="provider=LCPI.IBProvider.5;"
  +"location=localhost:d:\\database\\ram\\ibp_test_fb30_d3.gdb;"
  +"dbclient_type=fb.direct;"
  +"user id=gamer;"
  +"password=vermut;";

 //----------------------------------------------------------------------
 static int Main(string[] args)
 {
  int resultCode=0;

  OleDbConnection  cn=null;
  OleDbTransaction tr=null;
  OleDbCommand     cmd=null;
  OleDbDataReader  reader=null;

  try
  {
   cn=new OleDbConnection(c_cn_str);

   cn.Open();

   var dsinfo=cn.GetSchema(OleDbMetaDataCollectionNames.DataSourceInformation);

   Helper__CheckComponents(dsinfo);

   tr=cn.BeginTransaction();

   cmd=new OleDbCommand(null,cn,tr);

   //--------------------
   Console.WriteLine("Recreate TBL_WITH_IDENTITY ...");

   cmd.CommandText
    ="recreate table TBL_WITH_IDENTITY\n"
    +"(ID1 INTEGER GENERATED BY DEFAULT AS IDENTITY,\n"
    +" ID2 INTEGER)";

   cmd.ExecuteNonQuery();

   //--------------------
   Console.WriteLine("Commit retain ...");

   tr.CommitRetaining();

   //--------------------
   cmd.CommandText
    ="select ID1,ID2 from TBL_WITH_IDENTITY";

   reader
    =cmd.ExecuteReader(System.Data.CommandBehavior.SchemaOnly);

   var readerSchema=reader.GetSchemaTable();

   for(int i=0;i!=2;++i) //expected two rows
   {
    var readerSchemaRow=readerSchema.Rows[i];

    Console.WriteLine
     ("[{0}] {1} has autoincrement: {2}",
      i,
      readerSchemaRow[OleDbDataReaderSchemaColumnNames.ColumnName],
      readerSchemaRow[OleDbDataReaderSchemaColumnNames.IsAutoIncrement]);
   }//for i

   //--------------------
   Console.WriteLine("Commit ...");

   tr.Commit();
  }
  catch(Exception e)
  {
   resultCode=1;

   Console.WriteLine("");
   Console.WriteLine("ERROR: {0} - {1}",e.Source,e.Message);
  }//catch
  finally
  {
   structure_lib.DisposeUtils.Exec(ref cmd);
   structure_lib.DisposeUtils.Exec(ref tr);
   structure_lib.DisposeUtils.Exec(ref cn);
  }//finally

  return resultCode;
 }//Main

 //-----------------------------------------------------------------------
 private static void Helper__CheckComponents(System.Data.DataTable dsinfo)
 {
  Helper__CheckComponents_DBMS(dsinfo);
 }//Helper__CheckComponents
 
 //-----------------------------------------------------------------------
 private static void Helper__CheckComponents_DBMS(System.Data.DataTable dsinfo)
 {
  var row=dsinfo.Rows[0];

  var dbmsName
   =row[OleDbMetaDataCollectionColumnNames.DataSourceInformation.DataSourceProductName];

  var dbmsVersion
   =row[OleDbMetaDataCollectionColumnNames.DataSourceInformation.DataSourceProductVersion];
 
  if(DBNull.Value.Equals(dbmsName))
   throw new ApplicationException("DBMS Name is not defined!");

  if(DBNull.Value.Equals(dbmsVersion))
   throw new ApplicationException("DBMS Version is not defined!");

  if((string)(dbmsName)!="Firebird")
   throw new ApplicationException("Wrong DBMS name: "+dbmsName+". Expected \"Firebird\".");

  if(new Version((string)dbmsVersion)<new Version("3.0"))
   throw new ApplicationException("Wrong Firebird version: "+dbmsVersion+". Expected version not less than 3.0.");

  Console.WriteLine("OK. We work with {0} {1}",dbmsName,dbmsVersion);
 }//Helper__CheckDBMS
}//class Program

////////////////////////////////////////////////////////////////////////////////
}//Sample_0028

Ну и пока его ваял/тестировал, обнаружилась странная хрень с сервером. Он, то подключается, то не подключается. Никак не может определиться.

Как лично по мне — это очередная ахинея в сервере.

1 год

Привет всем.

Год назад был выпущен IBProvider v5.

🙂