View Issue Details

IDProjectCategoryView StatusLast Update
0003756SAS.ПланетаХотелка / Feature requestpublic09-04-2021 14:42
ReporterVadimK Assigned Tozed  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Product Version201212 
Target Version211230Fixed in Version211230 
Summary0003756: PascalScript: Добавить итерфейс для работы с тайлохранилищем (чтение, запись, инф. о тайле)
DescriptionЕсли скрипт скачивает тайл и сохраняет его в кэш на диск, то этот тайл не отображается на карте. Чтобы он отобразился, необходимо при просмотре карты изменить зум в ту или иную сторону и вернуть обратно. Тогда тайл отобразится (кстати, даже в случае, если переключалка "Кэш-Интернет" стоит в режиме "Интернет" (Alt-I))

Уже упоминал об этом на форуме (подробности
http://www.sasgis.org/forum/viewtopic.php?p=49956#p49956)
Steps To ReproduceСобственно, просьба:
ЕСЛИ
в params.txt установлено IsUseDownloaderInScript=1
И
скрипт возвращает ResultURL=''
ТО
проверять наличие тайла на диске,
и если он присутствует -- отображать тайл на карте
Additional InformationКонечно, из этой ситуации можно выйти другими способами.
Но у них есть недостатки.
Например, повторная перекачка тайла посредством указания ссылки в ResultURL увеличивает нагрузку на сервер. А указание в ResultURL локального пути до сохранённого тайла приводит к лишней файловой операции копирования.
TagsNo tags attached.
Attached Files
GarminQD_.zmp.zip (4,467 bytes)
AccessViolation.png (274,344 bytes)
AssertionFailure.png (127,663 bytes)   
AssertionFailure.png (127,663 bytes)   

Activities

zed

02-04-2021 12:36

manager   ~0020083

Вы как-то очень странно решили использовать скрипт, формирующий ссылку для загрузки тайла. Зачем вы качаете руками, то что SAS и так прекрасно может скачать?

Кроме того, из скрипта вы ведь в SQLite/Беркли тайлы сохранить не сможете, так что это очень сомнительная хотелка.

Возможно, вашу задачу можно решить другим способом, добавив, например, в скрипты вызовы OnBeforeDownload и OnAfterDownload. Или ещё как-то? Т.е. не вкорячивать абы что абы куда, а сделать по человечески?

VadimK

02-04-2021 13:15

reporter   ~0020084

Тайлы предварительно закачиваются руками, чтобы узнать их размер и при необходимости пополнить список/БД пустых тайлов. А раз уж тайл скачан, зачем его перекачивать повторно? Учитывая, что тайлов сотни тысяч а операция скачивания из интернета самая длительная, то получится неплохая экономия времени и снижение нагрузки на сервер, если повторного скачивания удастся избежать.

Касательно других типов кэша, в которых тайлы не хранятся пофайлово. Да, я думал об этом и мне это тоже не нравится. Но я до сих пор использую только второй тип.

Если задачу удастся решить другими способами, я буду только рад. :)
Надеюсь, там будет присутствовать функция добавления тайла в кэш _любого_ типа (это должна была быть моя следующая хотелка). А уж использование такой функции в скрипте было бы неплохим поводом для программы отобразить сохраняемый тайл на карте.

vdemidov

02-04-2021 13:33

manager   ~0020085

Я бы вообще запретил из скрипта любые операции с файловой системой. Пока только малая распространенность САС.Планеты спасает нас от ситуации: "Ой, я скачал с какого-то сайта zmp, попробовал посмотреть в САС, а все мои документы удалились"

Так что думайте как решить свои проблемы без прямого доступа к файлам и соответственно формулируйте хотелки. Эта хотелка, в том виде как она сейчас есть,с вероятностью 99% будет закрыта.

VadimK

02-04-2021 14:08

reporter   ~0020086

Last edited: 02-04-2021 14:25

Благодаря вашим замечаниям хотелка приобретает следующий вид.

Добавить для использования в скриптах функцию:

Function SaveTileToCache(X,Y,Z:integer; Tile:ansistring):boolean;

Она сохранит тайл именно в кэш того типа, который указан в params.txt
Эта функция безопасна для остальных пользовательских файлов на диске.

В режиме просмотра карты: если в скрипте задействуется эта функция (SaveTileToCache), то основная программа оповещается, что (не смотря на ResultURL='') тайл сохранён и его можно отобразить.

ЗЫ:
Почему Tile:AnsiString ? Потому что сюда пойдёт VResponseData, которая объявлена именно как AnsiString.

zed

02-04-2021 15:04

manager   ~0020087

Одной функции тут будет мало, тут уже речь про целый интерфейс - вам же наверняка ещё захочется проверить наличие тайла или .tne в кэше. И для записи в кэш ещё нужно указывать версию, content-type и т.д.

> Я бы вообще запретил из скрипта любые операции с файловой системой
Для этого придётся запретить вызывать dll в скриптах.

zed

02-04-2021 15:09

manager   ~0020088

> В режиме просмотра карты: если в скрипте задействуется эта функция (SaveTileToCache), то основная программа оповещается, что (не смотря на ResultURL='') тайл сохранён и его можно отобразить.

С этим как раз проблем нет - если запись в кэш происходит через интерфейс, то там есть оповещение об изменениях и гуй перерисовывается автоматически.

vdemidov

02-04-2021 15:45

manager   ~0020089

>Для этого придётся запретить вызывать dll в скриптах.
Ну, это еще большая дыра в безопасности. Спасает только то, что очень уж мало людей пользуется САС.Планетой - соответственно атака через эти дырки невыгодна. Но это не значит, что не стоит думать как прикрыть совсем уж вопиющие дырки или хотя бы не плодить новых.

zed

02-04-2021 16:19

manager   ~0020090

Считаешь ли ты интерфейс для взаимодействия с тайлохранилищем дырой?

vdemidov

02-04-2021 16:25

manager   ~0020091

> Считаешь ли ты интерфейс для взаимодействия с тайлохранилищем дырой?
Конечно нет. Другое дело, что ИМХО было бы полезней развить скриптовый движек другими типами скриптов (получение акутальной версии, предзапрос, пост обработка скачанного и тд.), вместо того что бы костылить все это внутри скрипта получения урла.
Но я, увы, понимаю насколько сложнее это сделать качественно, удобно, безопасно, логично и без ухудшения хотя бы обратной совместимости. Поэтому я, в принципе, за такой интерфейс.

zed

06-04-2021 16:42

manager   ~0020097

Last edited: 06-04-2021 16:42

Появился вопрос: а что делать если скрипт запускается из IDE? Может, от греха подальше, создавать хранилище в памяти и подставлять его?

vdemidov

06-04-2021 17:25

manager   ~0020098

> Появился вопрос: а что делать если скрипт запускается из IDE?
Да, думаю это правильно будет. Другое дело, что для отладки было бы хорошо видеть что там вышло в результате работы скрипта. А как это сделать удобно я не знаю.

zed

06-04-2021 18:46

manager   ~0020099

Да, сделаю наверное RAM кэш + сохранение дампа (в виде архива) на диск.

vdemidov

07-04-2021 12:09

manager   ~0020100

> Да, сделаю наверное RAM кэш + сохранение дампа (в виде архива) на диск.
ИМХО оптимальное решение. Я что-то про экспорт в виде архива не додумался.

zed

07-04-2021 12:39

manager   ~0020101

Можно тестировать использование интерфейса и из IDE. Единственное, что не доделано так это сохранение на диск, но в DebugOutput выводится вся информация о содержимом TileCache по окончании работы скрипта.


  TTileInfo = packed record
    IsExists    : Boolean;
    IsExistsTne : Boolean;
    LoadDate    : Int64; // unix timestamp
    Size        : Cardinal;
    Version     : string;
    ContentType : AnsiString;
    Data        : AnsiString;
  end;

  IPascalScriptTileCache = interface    
    function Read(
      const X: Integer;
      const Y: Integer;
      const AZoom: Byte;
      const AVersion: string;
      const AWithData: Boolean
    ): TTileInfo;

    function Write(
      const X: Integer;
      const Y: Integer;
      const AZoom: Byte;
      const AVersion: string;
      const AContentType: AnsiString;
      const AData: AnsiString;
      const AIsOverwrite: Boolean
    ): Boolean;

    function WriteTne(
      const X: Integer;
      const Y: Integer;
      const AZoom: Byte;
      const AVersion: string
    ): Boolean;

    function Delete(
      const X: Integer;
      const Y: Integer;
      const AZoom: Byte;
      const AVersion: string
    ): Boolean;
  end;

Пример использования:

procedure PrintInfo(var AInfo: TTileInfo);
begin
  Logger.WriteFmt(
    'IsExists: %d, IsExistsTne: %d, Size: %d, Content-Type: %s, Date: %d',
    [AInfo.IsExists, AInfo.IsExistsTne, AInfo.Size, AInfo.ContentType, AInfo.LoadDate]
  );
end;

var
  VInfo: TTileInfo;
  VResult: Boolean;
begin 
  VResult := TileCache.Write(0, 0, 0, '', 'image/png', '123', False);
  writeln(IntToStr(Integer(VResult)));
  
  VInfo := TileCache.Read(0, 0, 0, '', True);
  PrintInfo(VInfo);
  
  VResult := TileCache.WriteTne(0, 0, 0, '');
  writeln(IntToStr(Integer(VResult)));
  
  VInfo := TileCache.Read(0, 0, 0, '', True);
  PrintInfo(VInfo);
end.

zed

08-04-2021 07:26

manager   ~0020102

Last edited: 08-04-2021 07:26

Доделал, тестируйте. Дамп из IDE будет сохраняться в файл TileCacheDump.zip в корне с программой.

Пара советов по поводу вашего скрипта:
- не используйте ScriptBuffer для хранения информации об отсутствующих/пустых тайлах, а вместо этого записывайте tne в кэш (TileCache.WriteTne(...))
- надо задавать MaxConnectToServerCount=1 если вы не хотите, чтобы с сервера качалось несколько раз одно и то же разными экземплярами скрипта. Либо, весь свой код поместите в блокировку:

Global.Lock;
try
  // тут весь код формирования ResultURL
finally
  Global.Unlock;
end;

VadimK

09-04-2021 09:47

reporter   ~0020104

Last edited: 09-04-2021 09:48

Спасибо большое за быстрое добавление новой фичи в программу!
Только сегодня смог протестировать.
Но к сожалению вышеприведённый пример не заработал. :( Добавил скриншот в инцидент: [IMG]http://www.sasgis.org/mantis/file_download.php?file_id=2514&type=bug[/IMG]

Если уменьшить скрипт до:
[CODE]var
  VInfo: TTileInfo;
  VResult: Boolean;
begin
// VResult := TileCache.Write(0, 0, 0, '', 'image/png', '123', False);
  writeln(IntToStr(Integer(VResult)));
// VInfo := TileCache.Read(0, 0, 0, '', True);
end.[/CODE]
То работает.
Если раскомментировать первую строку, то тоже продолжает работать.
Но если расскоментировать последнюю строку, то снова ошибка, пока не закомментишь [B]_обе_[/B] строки обратно.

VadimK

09-04-2021 10:35

reporter   ~0020106

Last edited: 09-04-2021 11:08

[QUOTE="zed"]Пара советов по поводу вашего скрипта:
- не используйте ScriptBuffer для хранения информации об отсутствующих/пустых тайлах, а вместо этого записывайте tne в кэш (TileCache.WriteTne(...))[/QUOTE]
ScriptBuffer содержит координаты в гарминовском формате, более удобном для сравнения, чем XYZ. В гарминовском формате, чтобы узнать координаты (точнее, координатУ) вышележащего тайла, достаточно удалить одну цифру в координате текущего тайла. При работе же с кэшем (XYZ), как мне кажется, всё сильно усложнится и замедлится.

[QUOTE="zed"]надо задавать MaxConnectToServerCount=1 если вы не хотите, чтобы с сервера качалось несколько раз одно и то же разными экземплярами скрипта. Либо, весь свой код поместите в блокировку:[/QUOTE]Сразу после публикации скрипта на форуме (месяц назад) в личке мне подробно рассказали про Global.Lock|Unlock (с ссылками на примеры). И я собираюсь применить это в своём скрипте. Жаль, что в [URL=http://www.sasgis.org/wikisasiya/doku.php/%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D0%B0%D1%81%D0%BA%D0%B0%D0%BB%D1%8C_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2]описании скриптов на сайте[/URL] про эту полезную возможность не упоминается. :(

zed

09-04-2021 12:02

manager   ~0020109

> Добавил скриншот в инцидент:
Скриншот это хорошо, но ещё лучше - запустить SASPlanet.Debug.exe и приложить лог с ошибкой (появится файл с расширением .elf в корне с программой).

> ScriptBuffer содержит координаты
Этот буфер не переживёт перезапуска программы, а tne переживут. Чтобы определить координаты вышележащего тайла, достаточно сделать целочисленное деление координат текущего тайла на 2: X := GetX div 2; Y := GetY div 2;

zed

09-04-2021 12:06

manager   ~0020110

У меня ошибка не воспроизводится. Приложите, в дополнение к логу, ещё и params.txt из IDE.

VadimK

09-04-2021 12:58

reporter   ~0020111

Last edited: 09-04-2021 13:04

Запустил SASPlanet.Debug.exe
После закрытия окошка с ошибкой программа продолжает работать.
Файл [B].elf[/B] ни после возникновения ошибки, ни после закрытия программы не появился. Возможно потому, что ошибка возникла в PascalScript IDE.

В дебажной версии текст ошибки, кстати, изменился
Было [I]Access Violation[/I], стало [I]Assertion Failure[/I]:

[IMG]http://www.sasgis.org/mantis/file_download.php?file_id=2515&type=bug[/IMG]

PARAMS.TXT:
---
[PARAMS]
GUID={CBA03063-23D9-F11F-C22C-9182B98644B1}
asLayer=1
name_ru=Test
CacheType=2
projection=1
sradiusa=6378137
sradiusb=6378137
NameInCache=Test
Ext=.png
ContentType=image/png
UseDwn=1
---

Заархивировал всю папку с программой как есть:
https://disk.yandex.ru/d/hjS0L21U6fqkpw (18Mb)

zed

09-04-2021 13:32

manager   ~0020112

Вроде починил, тестируйте новую сборку.

VadimK

09-04-2021 14:38

reporter   ~0020113

Last edited: 09-04-2021 14:39

Ошибка ушла.
Ваш скрипт нормально работает.
Попробовал его упростить и разнообразить одновременно:
---
var
  VResult: Boolean;
begin
  VResult := TileCache.Write(GetX, GetY, GetZ, '', 'image/png', inttostr(GetX)+'-'+inttostr(GetY)+'-'+inttostr(GetZ), False);
  writeln(IntToStr(Integer(VResult)));
end.
---
Отработал этот скрипт нормально.

В режиме скачивания области по окончании процесса в статистике скачанных файлов/байт стоит 0.

[IMG]http://www.sasgis.org/mantis/file_download.php?file_id=2516&type=bug[/IMG]

Похоже, статистика подсчитывает только файлы, полученные через ResultURL.

PS: Попозже попробую интегрировать новые фишки в свой скрипт. Ещё раз, спасибо вам огромное за быструю реакцию на мои "хотелки" !!!

Issue History

Date Modified Username Field Change
02-04-2021 11:26 VadimK New Issue
02-04-2021 11:26 VadimK File Added: GarminQD_.zmp.zip
02-04-2021 12:36 zed Note Added: 0020083
02-04-2021 12:36 zed Assigned To => zed
02-04-2021 12:36 zed Status new => feedback
02-04-2021 13:15 VadimK Note Added: 0020084
02-04-2021 13:15 VadimK Status feedback => assigned
02-04-2021 13:33 vdemidov Note Added: 0020085
02-04-2021 14:08 VadimK Note Added: 0020086
02-04-2021 14:25 VadimK Note Edited: 0020086
02-04-2021 14:58 zed Assigned To zed =>
02-04-2021 14:58 zed Status assigned => new
02-04-2021 14:58 zed Summary сразу не отображаются тайлы, скачанные и сохранённые скриптом => PascalScript: Добавить итерфейс для работы с тайлохранилищем (чтение, запись, инф. о тайле)
02-04-2021 15:04 zed Note Added: 0020087
02-04-2021 15:09 zed Note Added: 0020088
02-04-2021 15:45 vdemidov Note Added: 0020089
02-04-2021 16:19 zed Note Added: 0020090
02-04-2021 16:25 vdemidov Note Added: 0020091
05-04-2021 08:33 zed Status new => confirmed
05-04-2021 08:33 zed Target Version => 211230
06-04-2021 16:42 zed Note Added: 0020097
06-04-2021 16:42 zed Note Edited: 0020097
06-04-2021 17:25 vdemidov Note Added: 0020098
06-04-2021 18:46 zed Note Added: 0020099
07-04-2021 12:09 vdemidov Note Added: 0020100
07-04-2021 12:39 zed Note Added: 0020101
08-04-2021 07:26 zed Note Added: 0020102
08-04-2021 07:26 zed Assigned To => zed
08-04-2021 07:26 zed Status confirmed => feedback
08-04-2021 07:26 zed Note Edited: 0020102
09-04-2021 09:38 VadimK File Added: AccessViolation.png
09-04-2021 09:47 VadimK Note Added: 0020104
09-04-2021 09:47 VadimK Status feedback => assigned
09-04-2021 09:48 VadimK Note Edited: 0020104
09-04-2021 10:35 VadimK Note Added: 0020106
09-04-2021 10:36 VadimK Note Edited: 0020106
09-04-2021 11:08 VadimK Note Edited: 0020106
09-04-2021 12:02 zed Note Added: 0020109
09-04-2021 12:06 zed Note Added: 0020110
09-04-2021 12:07 zed Status assigned => feedback
09-04-2021 12:52 VadimK File Added: AssertionFailure.png
09-04-2021 12:58 VadimK Note Added: 0020111
09-04-2021 12:58 VadimK Status feedback => assigned
09-04-2021 13:00 VadimK Note Edited: 0020111
09-04-2021 13:04 VadimK Note Edited: 0020111
09-04-2021 13:32 zed Note Added: 0020112
09-04-2021 13:32 zed Status assigned => feedback
09-04-2021 14:34 VadimK File Added: статистика_не_обновляется.png
09-04-2021 14:38 VadimK Note Added: 0020113
09-04-2021 14:38 VadimK Status feedback => assigned
09-04-2021 14:39 VadimK Note Edited: 0020113
09-04-2021 14:42 zed Status assigned => resolved
09-04-2021 14:42 zed Fixed in Version => 211230
09-04-2021 14:42 zed Resolution open => fixed
08-08-2025 13:24 zed Category Хотелка => Хотелка / Feature request