После внедрения подсистемы "Версионирование объектов" в первый же день стала возникать ошибка, связанная с нехваткой памяти. База 1с работает на платформе 8.3.6.
В отладчике отследили, что она возникает на вызове процедуры ЗаписатьXML() в функции СериализоватьОбъект() модуля ВерсионированиеОбъектов. Причем ошибка появляется только при записи объектов, у которых присутствует реквизит с типом ХранилищеЗначений.
Функция СериализоватьОбъект(Объект) Экспорт
ЗаписьXML = Новый ЗаписьFastInfoset;
ЗаписьXML.УстановитьДвоичныеДанные();
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписатьXML(ЗаписьXML, Объект, НазначениеТипаXML.Явное);
Возврат ЗаписьXML.Закрыть();
КонецФункции
В сети удалось найти обсуждение этой проблемы на форумах, но все рекомендации сводились к решению отключить версионирование либо некоторых объектов, либо в целом. Но в данном случае этот вариант не подходил, поскольку нужна запись версий всех справочников и документов.
В итоге, пришли к решению формировать XML с использованием базовой подсистемы, т.е. последовательной записи. Реквизиты с типом ХранилищеЗначений обрабатывать отдельно и записывать значение Неопределено. Ниже приводится измененная функция СериализоватьОбъект() и вспомогательные методы.
Функция СериализоватьОбъект(Объект) Экспорт
ЗаписьXML = Новый ЗаписьFastInfoset;
ЗаписьXML.УстановитьДвоичныеДанные();
ЗаписьXML.ЗаписатьОбъявлениеXML();
ИспользоватьПоследовательнуюЗаписьXML = Константы.ИспользоватьПоследовательнуюЗаписьXMLДляВерсионированияОбъектов.Получить();
Если Не ИспользоватьПоследовательнуюЗаписьXML Тогда
ЗаписатьXML(ЗаписьXML, Объект, НазначениеТипаXML.Явное);
Иначе
МетаданныеОбъекта = Объект.Метаданные();
Если ОбщегоНазначения.ЭтоСправочник(МетаданныеОбъекта) Тогда
ИмяОбъекта = "CatalogObject." + МетаданныеОбъекта.Имя;
ЗаписьXML.ЗаписатьНачалоЭлемента(ИмяОбъекта);
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("xs", "http://www.w3.org/2001/XMLSchema");
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("xsi", "http://www.w3.org/2001/XMLSchema-instance");
ЗаписьXML.ЗаписатьАтрибут("xsi:type", ИмяОбъекта);
ЗаписатьXML(ЗаписьXML, Объект.Ссылка.УникальныйИдентификатор(), "Ref", НазначениеТипаXML.Неявное);
Если ЕстьСтандартныйРеквизит(МетаданныеОбъекта.СтандартныеРеквизиты, "ЭтоГруппа") Тогда
ЗаписатьXML(ЗаписьXML, Объект.ЭтоГруппа, "IsFolder", НазначениеТипаXML.Неявное);
КонецЕсли;
ЗаписатьXML(ЗаписьXML, Объект.ПометкаУдаления, "DeletionMark",НазначениеТипаXML.Неявное);
Если ЕстьСтандартныйРеквизит(МетаданныеОбъекта.СтандартныеРеквизиты, "Владелец") Тогда
ЗаписатьXML(ЗаписьXML, Объект.Владелец, "Owner", НазначениеТипаXML.Явное);
КонецЕсли;
Если ЕстьСтандартныйРеквизит(МетаданныеОбъекта.СтандартныеРеквизиты, "Родитель") Тогда
ЗаписатьXML(ЗаписьXML, Объект.Родитель, "Parent", НазначениеТипаXML.Явное);
КонецЕсли;
Если ЕстьСтандартныйРеквизит(МетаданныеОбъекта.СтандартныеРеквизиты, "Код") Тогда
ЗаписатьXML(ЗаписьXML, Объект.Код, "Code", НазначениеТипаXML.Неявное);
КонецЕсли;
Если ЕстьСтандартныйРеквизит(МетаданныеОбъекта.СтандартныеРеквизиты, "Наименование") Тогда
ЗаписатьXML(ЗаписьXML, Объект.Наименование, "Description", НазначениеТипаXML.Неявное);
КонецЕсли;
ЗаписатьРеквизитыИТабличныеЧасти(Объект, МетаданныеОбъекта, ЗаписьXML);
ЗаписьXML.ЗаписатьКонецЭлемента();
ИначеЕсли ОбщегоНазначения.ЭтоДокумент(МетаданныеОбъекта) Тогда
ИмяОбъекта = "DocumentObject." + МетаданныеОбъекта.Имя;
ЗаписьXML.ЗаписатьНачалоЭлемента(ИмяОбъекта);
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("xs", "http://www.w3.org/2001/XMLSchema");
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("xsi", "http://www.w3.org/2001/XMLSchema-instance");
ЗаписьXML.ЗаписатьАтрибут("xsi:type", ИмяОбъекта);
ЗаписатьXML(ЗаписьXML, Объект.Ссылка.УникальныйИдентификатор(), "Ref", НазначениеТипаXML.Неявное);
ЗаписатьXML(ЗаписьXML, Объект.ПометкаУдаления, "DeletionMark", НазначениеТипаXML.Неявное);
ЗаписатьXML(ЗаписьXML, Объект.Дата, "Date", НазначениеТипаXML.Неявное);
ЗаписатьXML(ЗаписьXML, Объект.Номер, "Number", НазначениеТипаXML.Неявное);
ЗаписатьXML(ЗаписьXML, Объект.Проведен, "Posted", НазначениеТипаXML.Неявное);
ЗаписатьРеквизитыИТабличныеЧасти(Объект, МетаданныеОбъекта, ЗаписьXML);
ЗаписьXML.ЗаписатьКонецЭлемента();
Иначе
ЗаписатьXML(ЗаписьXML, Объект, НазначениеТипаXML.Явное);
КонецЕсли;
КонецЕсли;
Возврат ЗаписьXML.Закрыть();
КонецФункции
Процедура ЗаписатьРеквизитыИТабличныеЧасти(Объект, МетаданныеОбъекта, ЗаписьXML) Экспорт
Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл
Если Реквизит.Тип = Новый ОписаниеТипов("ХранилищеЗначения") Тогда
ЗаписатьXML(ЗаписьXML, Неопределено, Реквизит.Имя, НазначениеТипаXML.Неявное);
Иначе
ЗаписатьXML(ЗаписьXML, Объект[Реквизит.Имя], Реквизит.Имя, НазначениеТипаXML.Явное);
КонецЕсли;
КонецЦикла;
Для Каждого ТабличнаяЧасть Из МетаданныеОбъекта.ТабличныеЧасти Цикл
ЗаписьXML.ЗаписатьНачалоЭлемента(ТабличнаяЧасть.Имя);
Для Каждого Строка Из Объект[ТабличнаяЧасть.Имя] Цикл
ЗаписьXML.ЗаписатьНачалоЭлемента("Row");
Для Каждого Реквизит Из ТабличнаяЧасть.Реквизиты Цикл
Если Реквизит.Тип = Новый ОписаниеТипов("ХранилищеЗначения") Тогда
ЗаписатьXML(ЗаписьXML, Неопределено, Реквизит.Имя, НазначениеТипаXML.Неявное);
Иначе
ЗаписатьXML(ЗаписьXML, Строка[Реквизит.Имя], Реквизит.Имя, НазначениеТипаXML.Явное);
КонецЕсли;
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЦикла;
КонецПроцедуры
Функция ЕстьСтандартныйРеквизит(СтандартныеРеквизиты, Имя) Экспорт
ЕстьРеквизит = Ложь;
Для Каждого Реквизит Из СтандартныеРеквизиты Цикл
Если Реквизит.Имя = Имя Тогда
ЕстьРеквизит = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат ЕстьРеквизит;
КонецФункции
После перехода на последовательную запись XML ошибка перестала возникать. Конечно, это решение имеет свои недостатки. Например, запись XML для документа с 2000 строками табличной части выполняется не одну секунду, а пять. Но можно развить это решение, введя дополнительный признак, какой метод записи XML использовать для конкретного справочника или документа как объекта метаданных. И использовать последовательную запись XML только для объектов, имеющих реквизиты с типом ХранилищеЗначений.