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

Только для тех, кто пишет плагины под Total Commander. Обмен опытом, решение проблем.

Модераторы: d-view, Моторокер, Avada, CaptainFlint, Nik

Ответить
Gentoo69
Сообщения: 68
Зарегистрирован: Вс июл 11, 2010 19:58

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

Сообщение Gentoo69 »

Покажу на примере. Пишу 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;

Из за этого портачится все кэширование. Приходится открывать один файл по три четыре раза и парсить его столько же.
Что за фигня, это баг или фича? Как это можно обойти?
Аватара пользователя
MVV
Сообщения: 4815
Зарегистрирован: Чт окт 15, 2009 10:58
Откуда: Ростов-Дон

Сообщение MVV »

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

А на порядок сортировки файлов в панели лучше вообще не смотреть.
Gentoo69
Сообщения: 68
Зарегистрирован: Вс июл 11, 2010 19:58

Сообщение Gentoo69 »

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

А на порядок сортировки файлов в панели лучше вообще не смотреть.
Я ему написал письмо, посмотрим что он скажет
Loopback
Сообщения: 1646
Зарегистрирован: Пн сен 07, 2009 09:29

Сообщение Loopback »

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

Код: Выделить всё

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.
Получается, что запрос полей для следующего файла начинается только после завершения с предыдущим.
Аватара пользователя
MVV
Сообщения: 4815
Зарегистрирован: Чт окт 15, 2009 10:58
Откуда: Ростов-Дон

Сообщение MVV »

Хм, действительно. Написал тестовый плагин с полями разных типов, возвращающий последовательные числа (или числа в виде строки):

Код: Выделить всё

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
[/size]
Причем, при любой стандартной сортировке.

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

Ага, вот что:

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

Код: Выделить всё

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
[/size]

А теперь попробую отсортировать по двум столбцам...

Код: Выделить всё

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
[/size]
Но почему-то данное правило не всегда имеет место при сложных сортировках - то ТК запрашивает по-порядку поля, по которым идет сортировка, а затем остальные, то тупо запрашивает все поля подряд...
Gentoo69
Сообщения: 68
Зарегистрирован: Вс июл 11, 2010 19:58

Сообщение Gentoo69 »

В моем случае получается, - нужно распаковать zip . Открыть файл. Распарсить файл.
Получается несколько раз приходится делать эти операции с одним файлом. При больших кол. файлов это slow as hell.
Пока придется юзерам писать чтобы не включали custom сортировку на больших массивах
Если включить сортировку по полю плагина, то ТК вначале запросит это поле для всех файлов, а затем последовательно запросит остальные поля в обычном режиме.
Глупо как то, не вижу никаких технических преград так делать, сразу бы запросил все поля..
Gentoo69
Сообщения: 68
Зарегистрирован: Вс июл 11, 2010 19:58

Сообщение Gentoo69 »

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

You wrote:
[...]
> 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.

> 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.


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

Напишите ответ здесь, я ему отправлю. Или сами отправьте.
Аватара пользователя
MVV
Сообщения: 4815
Зарегистрирован: Чт окт 15, 2009 10:58
Откуда: Ростов-Дон

Сообщение MVV »

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

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

Или сам храни в мэпе данные для всего каталога, и выбирай нужное...
Gentoo69
Сообщения: 68
Зарегистрирован: Вс июл 11, 2010 19:58

Сообщение Gentoo69 »

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

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

Или сам храни в мэпе данные для всего каталога, и выбирай нужное...
Тут ерунда получается, пока не заполнятся все колонки, все равно список не появится. Просто будет висеть значок песочных часов, а потом уже появится список со всеми заполненными колонками. Вот так вот.
Я попросил его чтобы он ввел флаг, который фиксит подобное поведение (т.е. флаг, который заставляет total запрашивать все колонки, на один файл, даже если включена сортировка по колонке плагина) . Может введет . Надеюсь.
Аватара пользователя
MVV
Сообщения: 4815
Зарегистрирован: Чт окт 15, 2009 10:58
Откуда: Ростов-Дон

Сообщение MVV »

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

Код: Выделить всё

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

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

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

Код: Выделить всё

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;
}
Gentoo69
Сообщения: 68
Зарегистрирован: Вс июл 11, 2010 19:58

Сообщение Gentoo69 »

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

За советы спасибо
Gentoo69
Сообщения: 68
Зарегистрирован: Вс июл 11, 2010 19:58

Сообщение Gentoo69 »

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

http://forum.wincmd.ru/viewtopic.php?t=13363
Ответить