Total Commander Forum Index Total Commander
Форум поддержки пользователей Total Commander
Сайты: Все о Total Commander | Totalcmd.net | Ghisler.com | RU.TCKB
 
 RulesRules   SearchSearch   FAQFAQ   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Content plugin - странная работа функции ContentGetValue

 
Post new topic   Reply to topic    Total Commander Forum Index -> Написание плагинов для Total Commander printer-friendly view
View previous topic :: View next topic  
Author Message
Gentoo69



Joined: 11 Jul 2010
Posts: 68

Post (Separately) Posted: Mon Jul 12, 2010 17:52    Post subject: Content plugin - странная работа функции ContentGetValue Reply with quote

Покажу на примере. Пишу wdx плагин.

Допустим в папке лежит 3 файла.
File 1
File 2
File 3

Если отсортировать по внутренним полям - Name или Ext - то ContentGetValue работает правильно, а именно:

1. File1 FieldIndex (my fieldindex) = 0;
2. File1 FieldIndex (my fieldindex) = 1;

3. File2 FieldIndex (my fieldindex) = 0;
4. File2 FieldIndex (my fieldindex) = 1;

Т.е. возвращает имена файлов подряд.

А если рассортировать по одной из моих колонок (полей), и выйти и зайти в папку опять ,то функция уже будет работать по другому:

1. File1 FieldIndex (my fieldindex) = 0;
2. File2 FieldIndex (my fieldindex) = 0;
3. File1 FieldIndex (my fieldindex) = 1;
4. File2 FieldIndex (my fieldindex) = 1;

Из за этого портачится все кэширование. Приходится открывать один файл по три четыре раза и парсить его столько же.
Что за фигня, это баг или фича? Как это можно обойти?
Back to top
View user's profile Send private message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Mon Jul 12, 2010 18:04    Post subject: Reply with quote

Кэширование в контентном плагине - большая проблема. К сожалению, ТК получает поля не по файлам, получая последовательно все поля для каждого отдельно взятого файла, а по колонкам, запрашивая вначале первое поле для каждого файла, затем второе и т.п. Так что или без кэширования, или с кэшированием всех полей для всей папки. Кстати, интересно, предлагали ли Гислеру запрашивать поля по строкам (файлам), а не по столбцам.

А на порядок сортировки файлов в панели лучше вообще не смотреть.
_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
Gentoo69



Joined: 11 Jul 2010
Posts: 68

Post (Separately) Posted: Mon Jul 12, 2010 18:12    Post subject: Reply with quote

MVV wrote:
Кэширование в контентном плагине - большая проблема. К сожалению, ТК получает поля не по файлам, получая последовательно все поля для каждого отдельно взятого файла, а по колонкам, запрашивая вначале первое поле для каждого файла, затем второе и т.п. Так что или без кэширования, или с кэшированием всех полей для всей папки. Кстати, интересно, предлагали ли Гислеру запрашивать поля по строкам (файлам), а не по столбцам.

А на порядок сортировки файлов в панели лучше вообще не смотреть.


Я ему написал письмо, посмотрим что он скажет
Back to top
View user's profile Send private message
Loopback



Joined: 07 Sep 2009
Posts: 1274

Post (Separately) Posted: Mon Jul 12, 2010 20:24    Post subject: Reply with quote

MVV
Хм. А как тогда понимать это (цитата из описания):
Code:

Total Commander will not call a mix ContentGetValue for different files, it will only call it for the next file when the previous file can be closed. Therefore a single cache per running Total Commander would be sufficient.

Получается, что запрос полей для следующего файла начинается только после завершения с предыдущим.
Back to top
View user's profile Send private message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Mon Jul 12, 2010 21:18    Post subject: Reply with quote

Хм, действительно. Написал тестовый плагин с полями разных типов, возвращающий последовательные числа (или числа в виде строки):
Code:
avifile.dll   1   2   3   4   5
axaltocm.dll   6   7   8   9   10
basecsp.dll   11   12   13   14   15
basesrv.dll   16   17   18   19   20
BASSMOD.dll   21   22   23   24   25
batmeter.dll   26   27   28   29   30
batt.dll   31   32   33   34   35
bcsprsrc.dll   36   37   38   39   40
BDEADMIN.CPL   41   42   43   44   45
bidispl.dll   46   47   48   49   50
bios1.rom   51   52   53   54   55
bios4.rom   56   57   58   59   60
bitsprx2.dll   61   62   63   64   65
bitsprx3.dll   66   67   68   69   70
blackbox.dll   71   72   73   74   75
blastcln.exe   76   77   78   79   80
bootcfg.exe   81   82   83   84   85
bootok.exe   86   87   88   89   90
bootvid.dll   91   92   93   94   95
bootvrfy.exe   96   97   98   99   100
bopomofo.uce   101   102   103   104   105
browselc.dll   106   107   108   109   110
browser.dll   111   112   113   114   115
browseui.dll   116   117   118   119   120
browsewm.dll   121   122   123   124   125
bthci.dll   126   127   128   129   130
bthprops.cpl   131   132   133   134   135
bthserv.dll   136   137   138   139   140
btpanui.dll   141   142   143   144   145
c_037.nls   146   147   148   149   150
c_10000.nls   151   152   153   154   155

Причем, при любой стандартной сортировке.

Даже не знаю, что меня тогда сбило, когда я писал NTLinks, но вроде смотрел и заметил, что по столбцам.

Ага, вот что:

Если включить сортировку по полю плагина, то ТК вначале запросит это поле для всех файлов, а затем последовательно запросит остальные поля в обычном режиме. Угадайте, по какому столбцу сортировка: Smile
Code:
avifile.dll   842   843   807   844   845
axaltocm.dll   846   847   808   848   849
basecsp.dll   850   851   809   852   853
basesrv.dll   854   855   810   856   857
BASSMOD.dll   858   859   811   860   861
batmeter.dll   862   863   812   864   865
batt.dll   866   867   813   868   869
bcsprsrc.dll   870   871   814   872   873
BDEADMIN.CPL   874   875   815   876   877
bidispl.dll   878   879   816   880   881
bios1.rom   882   883   817   884   885
bios4.rom   886   887   818   888   889
bitsprx2.dll   890   891   819   892   893
bitsprx3.dll   894   895   820   896   897
blackbox.dll   898   899   821   900   901
blastcln.exe   902   903   822   904   905
bootcfg.exe   906   907   823   908   909
bootok.exe   910   911   824   912   913
bootvid.dll   914   915   825   916   917
bootvrfy.exe   918   919   826   920   921
bopomofo.uce   922   923   827   924   925
browselc.dll   926   927   828   928   929
browser.dll   930   931   829   932   933
browseui.dll   934   935   830   936   937
browsewm.dll   938   939   831   940   941
bthci.dll   942   943   832   944   945
bthprops.cpl   946   947   833   948   949
bthserv.dll   950   951   834   952   953
btpanui.dll   954   955   835   956   957
c_037.nls   958   959   836   960   961
c_10000.nls   838   839   837   840   841


А теперь попробую отсортировать по двум столбцам...
Code:
avifile.dll   1   63   2   64   65
axaltocm.dll   3   66   4   67   68
basecsp.dll   5   69   6   70   71
basesrv.dll   7   72   8   73   74
BASSMOD.dll   9   75   10   76   77
batmeter.dll   11   78   12   79   80
batt.dll   13   81   14   82   83
bcsprsrc.dll   15   84   16   85   86
BDEADMIN.CPL   17   87   18   88   89
bidispl.dll   19   90   20   91   92
bios1.rom   21   93   22   94   95
bios4.rom   23   96   24   97   98
bitsprx2.dll   25   99   26   100   101
bitsprx3.dll   27   102   28   103   104
blackbox.dll   29   105   30   106   107
blastcln.exe   31   108   32   109   110
bootcfg.exe   33   111   34   112   113
bootok.exe   35   114   36   115   116
bootvid.dll   37   117   38   118   119
bootvrfy.exe   39   120   40   121   122
bopomofo.uce   41   123   42   124   125
browselc.dll   43   126   44   127   128
browser.dll   45   129   46   130   131
browseui.dll   47   132   48   133   134
browsewm.dll   49   135   50   136   137
bthci.dll   51   138   52   139   140
bthprops.cpl   53   141   54   142   143
bthserv.dll   55   144   56   145   146
btpanui.dll   57   147   58   148   149
c_037.nls   59   150   60   151   152
c_10000.nls   61   153   62   154   155

Но почему-то данное правило не всегда имеет место при сложных сортировках - то ТК запрашивает по-порядку поля, по которым идет сортировка, а затем остальные, то тупо запрашивает все поля подряд...
_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
Gentoo69



Joined: 11 Jul 2010
Posts: 68

Post (Separately) Posted: Mon Jul 12, 2010 22:38    Post subject: Reply with quote

В моем случае получается, - нужно распаковать zip . Открыть файл. Распарсить файл.
Получается несколько раз приходится делать эти операции с одним файлом. При больших кол. файлов это slow as hell.
Пока придется юзерам писать чтобы не включали custom сортировку на больших массивах

Quote:
Если включить сортировку по полю плагина, то ТК вначале запросит это поле для всех файлов, а затем последовательно запросит остальные поля в обычном режиме.


Глупо как то, не вижу никаких технических преград так делать, сразу бы запросил все поля..
Back to top
View user's profile Send private message
Gentoo69



Joined: 11 Jul 2010
Posts: 68

Post (Separately) Posted: Tue Jul 13, 2010 15:08    Post subject: Reply with quote

Ответ Гислера:

You wrote:
Quote:
[...]
> If sorting order is by name or ext, ContentGetValueW return:
> 1. File1 FieldIndex (my fieldindex) = 0;
> 2. File1 FieldIndex (my fieldindex) = 1;
> 3. File2 FieldIndex (my fieldindex) = 0;
> 4. File2 FieldIndex (my fieldindex) = 1;
> Its work nice so I can cach last file in buffer.


That's because Total Commander requests the fields only when it displays them.


Quote:
> But if click on my column (any), to sort it, and then enter to folder again, ContentGetValueW return:

> 1. File1 FieldIndex (my fieldindex) = 0;
> 2. File2 FieldIndex (my fieldindex) = 0;
> 3. File1 FieldIndex (my fieldindex) = 1;
> 4. File2 FieldIndex (my fieldindex) = 1;


What happens here is that Total Commander first gets just the field by which
you are sorting (field 0). Later when the lines are displayed, Total Commander
requests the fields which have not been requested yet.

This is done because it's not a good idea to request all fields when sorting,
because the fields by which you don't currently sort may be very slow to
load.


I think that you don't need to cache the entire directory in this case, caching
by file is OK.


------------------
Мля, как же я будут кэшировать файл я не пойму?

Напишите ответ здесь, я ему отправлю. Или сами отправьте.
Back to top
View user's profile Send private message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Tue Jul 13, 2010 15:34    Post subject: Reply with quote

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

Кэшировать по идее можно все равно - ну будет в 2 раза медленнее с учетом того, что вначале сортировочные колонки будут получаться, а потом остальные...

Или сам храни в мэпе данные для всего каталога, и выбирай нужное...
_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
Gentoo69



Joined: 11 Jul 2010
Posts: 68

Post (Separately) Posted: Tue Jul 13, 2010 15:48    Post subject: Reply with quote

MVV wrote:
Ну вообще да, смысл есть, поля ведь запрашиваются в фоновом потоке, а сортировка должна быть выполнена в первую очередь.

Кэшировать по идее можно все равно - ну будет в 2 раза медленнее с учетом того, что вначале сортировочные колонки будут получаться, а потом остальные...

Или сам храни в мэпе данные для всего каталога, и выбирай нужное...


Тут ерунда получается, пока не заполнятся все колонки, все равно список не появится. Просто будет висеть значок песочных часов, а потом уже появится список со всеми заполненными колонками. Вот так вот.
Я попросил его чтобы он ввел флаг, который фиксит подобное поведение (т.е. флаг, который заставляет total запрашивать все колонки, на один файл, даже если включена сортировка по колонке плагина) . Может введет . Надеюсь.
Back to top
View user's profile Send private message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Tue Jul 13, 2010 16:08    Post subject: Reply with quote

А ты не забывай про фоновый подсчет содержимого поля - ты сам должен сказать ТК, что поле можно подсчитать в фоне:
Code:
if (Flags&CONTENT_DELAYIFSLOW) return ft_delayed;

При этом все поля, при первом обращении к которым было возвращено ft_delayed, будут повторно запрошены в фоне (но уже без флага CONTENT_DELAYIFSLOW), позволяя работу с панелью до завершения заполнения колонок. Разумеется, если поле отвечает за сортировку, это поле будет запрошено в основном потоке в любом случае (флага CONTENT_DELAYIFSLOW не будет сразу).

И не забывай о синхронизации потоков, если используешь кэширование или другие глобальные переменные, совместный доступ к которым чреват глюками.

В моем тестовом плагине я добавил упомянутую выше строчку в начале функции ContentGetValueW, чтобы сделать все свои поля фоновыми, а потом поставил Sleep(256). Таким образом, на подсчет значения каждого поля уходит более 256 мс. И очень хорошо видно, что, пока тотал запрашивает значения сортировочного столбца, он висит, а значения в остальных столбцах появляются потом постепенно.

Code:
int __stdcall ContentGetValueW(WCHAR* FileName, int FieldIndex, int UnitIndex, void* FieldValue, int MaxLen, int Flags) {
   if (FieldIndex>=IF_END) return ft_nosuchfield;

   int error=0;

   if (Flags&CONTENT_DELAYIFSLOW) return ft_delayed;

   ++counter;
   Sleep(256);

   switch (Fields[FieldIndex].Type) {
      case ft_numeric_32: {
         *(int*)FieldValue=counter;
         break;
      }
      case ft_string: {
         wsprintfA((char*)FieldValue, "%d", counter);
         break;
      }
      case ft_stringw: {
         wsprintfW((wchar_t*)FieldValue, L"%d", counter);
         break;
      }
      default: {
         error=ft_fieldempty;
      }
   }

   return error ? error : Fields[FieldIndex].Type;
}

_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
Gentoo69



Joined: 11 Jul 2010
Posts: 68

Post (Separately) Posted: Tue Jul 13, 2010 17:04    Post subject: Reply with quote

Quote:
А ты не забывай про фоновый подсчет содержимого поля - ты сам должен сказать ТК, что поле можно подсчитать в фоне:


Да это я не на своем плагине смотрел, а на том, на который пишу быстрый аналог (wdx_xml - собстно поэтому и пишу - чтение fb2.zip и fb2). В моем случае работает все быстро, но было бы еще быстрее если бы запрашивались все колонки на текущий файл.

За советы спасибо
Back to top
View user's profile Send private message
Gentoo69



Joined: 11 Jul 2010
Posts: 68

Post (Separately) Posted: Fri Jul 16, 2010 14:20    Post subject: Reply with quote

Бета версия плагина:

http://forum.wincmd.ru/viewtopic.php?t=13363
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Total Commander Forum Index -> Написание плагинов для Total Commander All times are GMT + 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group