<?php // Полная загрузка сервисных книжек, создан 2025-01-05 12:44:55
global $wpdb2;
global $failure;
global $file_hist;
///// echo '<H2><b>Старт загрузки</b></H2><br>';
$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
///// echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}
$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
///// echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}
/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
///// echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
///// echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist); ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7]; ////получаем размер файла
$m_mtime_file=$masiv_data_file[9]; ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file
///// echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
///// echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
///// echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);
if ($results)
{ foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));
////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
///// echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
///// echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}
////загружаем данные
$table='vin_history'; // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация // (путь от корня web-сервера)
$delim=';'; // Разделитель полей в CSV файле
$enclosed='"'; // Кавычки для содержимого полей
$escaped='\
Нет ли ошибки в названии? Дело в том, что в 8.3 есть встроенная функция для решения этой задачи.
Второй вопрос: какой именно CRC32 вычисляли? — Там есть стандартный IEEE, CRC32С, CRC32Q.
Сравнивали результаты с полученными независимо другими методами?
(1) В названии ошибки нет. Как раз в названии явно указано, что алгоритм предназначен для платформ 1С:Предприятие версий старше 8.3 (8.2, 8.1, 8.0, я так полагаю и на 7.7 можно алгоритм реализовать).
NoName и написанной тогда мной на С++ программе, реализующей этот же алгоритм.
Какой именно вариант алгоритма применялся я уже и не помню, давно всё это писалось (лет 5 назад), а вот опубликовать решил только сейчас. Предполагаю, что стандартный.
Результаты проверял в онлайн калькуляторе
(1) Вот нашел исходные коды этого алгоритма на С++http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/libkern/crc32.c . Это алгоритм CRC-32-IEEE 802.3.
(2) мне кажется, что вы путаете слова «старше» и «старее». Версия 8.3 старше 8.2. Версия 8.2 старее 8.3. Или я ошибаюсь?
Нумерация версий программного обеспечения
См.:
(4) ildarovich, Вы, к сожалению, ошибаетесь. Слова «старше» и «старее» — синонимы. Приведу простой пример: если сравнить годы выпуска платформ 8.0 и 8.3, то по «возрасту» 8.0 окажется значительно старше (ну, или «старее» — кому как нравится). Сравните Ваш возраст и возраст Ваших родителей. Кто из вас старше?
(5) это «наивное» объяснение. И неправильное.
По ссылке в Википедии статью прочитали? Старшая версия — это более зрелая версия, вбирающая, как правило, в себя часть кода более ранней версии.
(6) ildarovich, всё это — полемика по определению старшинства версий. Конечно, на первый взгляд кажется, что версия платформы 1С:Предприятие 8.3 «старше», чем версия 8.2. Но, в посте (4) я уже указал причину, по которой версия 8.3 является младшей — дату её выпуска. Материалы из «Википедии» — ни о чём. Ведь там за основу взят номер релиза (подрелиза) и т. д., а я имел в виду именно старшие по «возрасту» платформы 1С:Предприятия. Если Вам кажется, что название публикации может ввести пользователей InfoStart’а в заблуждение, я совсем не против изменить наименование публикации (если есть желание, можете подсказать, как «грамотно» с Вашей точки зрения, её именовать). Наверное, так и сделаю к моменту выхода еженедельного обзора. Хотя, если вдуматься в название публикации, можно даже удалить её из раздела публичного доступа. Ведь, по-вашему, в названии явная ошибка — не существует на данный момент платформы 1С:Предприятия «старше» версии 8.3. Предлагаю полемику о старшинстве версий ПО закончить. Если есть замечания по опубликованному функционалу — пишите. Критику воспринимаю адекватно.
(7) поскольку тема мне интересна, позволю себе высказать свои соображения по-поводу самого решения. Не хотел бы, чтобы вы воспринимали это как критику — это заметки для тех, кто захочет улучшить это решение, если увидит в этом необходимость.
1) кодовую таблицу utf-8 — windows 1251 можно не хранить в макете, а быстро и просто получить вот такой функцией:
Показать
В строке символы utf-8, их позиция — это код windows-1251. Но, вообще говоря, непонятно, к чему это преобразования — почему не брать все байты utf-8?
2) При всем богатстве операций с числами в языке 1С есть ли необходимость использовать строку для представления и работы с двоичными числами? Сдвиг вправо — это деление на 256. Логическое «И» с FF это нахождение остатка от деления на 256. «ХОR» можно сделать побайтно (по-полубайтно) по таблицам (два байта — вход, один — выход). Тем более, что таблицы для предпросчета восьми сдвигов входного символа вы все же используете. Инверсия — это тот же XOR с FFFFFFFF. Таблицы лучше загнать заранее в массив. Насчет XOR можно еще подумать — как его смоделировать.
3) Таблицы в макете — очень не гибко. Лучше из все же рассчитывать и хранить, например, в параметрах обработки. Это не так уж долго.
В целом так может довольно большой выигрыш по быстродействию получиться.
Интересно, сколько времени занимает у вас сейчас расчет контрольной суммы для строки из 1222 символов?
Можно будет сравнить быстродействие. У меня, например, есть запрос, внутри которого вычисляется CRC32Q (или любой другой — там характеристический полином прямо в таблице задается).
Если будете делать замеры, чтобы привести их к общему знаменателю, лучше указать, сколько таких строк можно обработать за минуту.
(8) ildarovich, по поводу Ваших заметок:
1. Изначально я предполагал, такой же подход, смотрите, что получается при вызове этой функции:
И результат:
? = 63
? = 63
? = 63
? = 63
? = 63
= 1
= 2
= 3
= 4
= 5
= 6
= 7
= 8
= 9
= 10
……..
А = 1 040
Б = 1 041
В = 1 042
Г = 1 043
Д = 1 044
Е = 1 045
Ж = 1 046
З = 1 047
И = 1 048
………
Поэтому-то я и загнал таблицу кодов в макет (макет — из соображений не загромождать текст модуля).
2. Не спорю логика есть — операции с числами, несомненно производятся быстрее, но на момент написания этих алгоритмов, пришло такое вот решение. К тому же для выполнения «XOR» все равно понадобилось бы двоичное представление числа.
3. Про таблицы в макете я уже писал выше — не хотелось загромождать программный код.
Вот что я действительно не предусмотрел для расчета CRC, это проинициализировать массив данных для расчета перед выполнением функции, а не получать их из макета в цикле.
Интересно, сколько времени занимает у вас сейчас расчет контрольной суммы для строки из 1222 символов?
Заняло 21 сек. Много, конечно, но мне и не требовалось обрабатывать символные массивы таких размеров. Требовалось обрабатывать строки длиной порядка 30-40 символов, а это уже 1 сек. на выполнение, что в общем-то для моей задачи оказалось приемлемым.
Хотя, я, конечно, всё равно в последующем заменил функцию расчета CRC32 на аналогичную функцию внешней компоненты. А изложенную выше оставил, так сказать, для истории :).
(8) ildarovich, забыл задать встречный вопрос к п.2: с операцией «AND» всё понятно, Вы привели пример, а как же остальные операции рассчитывать?
Инверсия — это тот же XOR с FFFFFFFF
Но Вы же не привели пример, как рассчитать XOR используя только числовые показатели и встроенные функции для работы с числами….
(8) ildarovich, не внимательно я прочитал Ваш ответ в п.1. и, соответственно, сделал неправильные выводы в посте 9.
Действительно, в возвращаемой функцией строке номер символа является его кодом в таблице ASCII. Ну, как говорится: «Век живи — век учись». Спасибо за подсказку.
(10)
Простая и быстрая хэш функция (hash) средствами 1С (оптимизированный вариант) предлагается решение, позволяющее рассчитать для такой строки 21000 хэшей в минуту! Притом 64-разрядных! Пусть не CRC32.
запросе получается примерно 12000 хэшей в минуту, а для коротких строк из цифр (всякие коды справочников) еще намного больше.
1) — чуть позже
21 сек. — это очень, очень много. Получается 3 хэша в минуту. Тогда как в статье
У меня в запросе (!!!) получалось (для CRC32) порядка 1000 хэшей минуту (сейчас не ручаюсь, нужно перепроверить). Я счел этот показатель ниже всякой критики и перешел на арифметический хэш, где в
После обдумывания возможных путей достижения максимальной скорости предлагается вот такой рабочий вариант:
1) хранить текущее состояния регистра сдвига в «разреженном» числе. При этом на каждый бит регистра будет приходится три бита числа. Это нужно для того, чтобы заменить XOR обычным сложением, чтобы не мешали межразрядные переносы.
2) предрассчитать таблицу ОС (и загнать в массив 2#k8SjZc9Dxk24) отображения младшего байта регистра (растянутого на три байта) в сумму, которые нужно добавлять к регистру через обратные связи. Хотя массив будет занимать 2#k8SjZc9Dxk24, заполненным там будет всего 5#k8SjZc9Dxk8 ~ 100000 элементов.
3) предрассчитать отображения символа в «разреженный» байт.
Алгоритм будет таким:
Для каждого символа:
1) Добавляем разреженный байт символа к регистру;
2) Выделяем младший разреженный байт через %;
3) Вычитаем его из регистра и делим регистр на 2#k8SjZc9Dxk24, чтобы получить сдвиг на 8 реальных бит (24 разреженных);
4) Находим добавляемую суммы по разреженному байту из таблицы ОС;
5) Добавляем эту сумму к регистру
Записал просто, чтобы не забыть. Основная идея в том, что XOR — это четность, а четность суммы — это младший бит. В регистре делается всего четые сложения «за оборот», поэтому сумма не выйдет за «100» (двоичный код 4) и для ее хранения будет достаточно трех бит.
(12) ildarovich, 21 сек. — это очень, очень много.
Конечно много! Я и сам утверждаю это в посте (9).
Ваши публикации, указанные в ссылках поста я прочитал. Очень познавательно! Надо будет вернуться и поставить «плюс».
Предложенный Вами рабочий вариант пока что не получилось осмыслить (вернусь к этому позже при необходимости).
Ну что же, исходя из того, что предложенные Вами решения (по ссылкам в посте (12)) оказались реально более скоростными, предлагаю рассматривать мою публикацию как «опыт неоптимального программирования» :). Ведь отрицательный опыт — тоже опыт, и надо только знать, как его использовать.
(13) это нужно рассматривать как хороший учебный пример.
Во-первых, код очень хорошо структурирован и замечательно оформлен, снабжен множеством нужных при отладке проверок.
Во-вторых, реализован один из возможных быстрых алгоритмов (при реализации на другом языке), где в отладчике можно проследить по шагам его работу, чтобы разобраться в выполняемых преобразованиях (символ за такт — это не символ за восемь тактов, как при решении задачи «в лоб»).
Так что тщательно сделанная работа бесполезной не бывает.
Спасибо! Надеюсь, кому-нибудь пригодится.
Ув. Максим! Вы если ставите флажек, насчет поддержки «Все платформы», то уж выкладывайте обработку в версии и 8.0! А так получился лохотрон, мне каким образом Ваш макет использовать в версии 8.1?
(16) Ув. kylux. Вот уж просто не подумал, что кто-то ещё использует платформы версий 8.0 или 8.1. Когда я эту обработку писал, уже 8.2 вовсю использовали. Ну, файл-то Вы не скачивали, значит и не потеряли ничего )))
(16) Прошу прощения за неточность: файл Вы скачивали (раньше подпись была у комментария «файл скачал», сейчас её убрали к сожалению, вот и получилось недоразумение). Если хотите, могу купить что-нибудь из Ваших наработок, чтобы вернуть Вам потраченные $m.
Доброго времени суток. Замечание — пришлось для нас сделать доработку, у вас исключаются из расчета контрольной суммы пустые строки, а нам это нужно. На пустых строках тоже все заработало без проблем. Спасибо за обработку 🙂
(19) Очень интересно, как же вы контрольную сумму пустой строки вычисляете?