| Mikhail Sukhov 
 
   
 
						
						
					 | Date: 1/24/2011 
						
							|  |  |  |   |  
 
 
	
			aspirant Дело в том, что работа с плазовским стримом построена по принципу windows message loop: в неком методе программа вызывает метод CP2ConnectionClass.ProcessMessage(out cookie, PollInterval) в бесконечном цикле, а вся информация приходит через события.  Если выводить создание и управление thread'ами, это нужно делать в отдельном классе.  Иначе, если придется подключаться к стримам в нескольких местах, придется дублировать много кода.
 
 Дубляж - это плохо. И плохо, когда стрим создает потоки (кол-во потоков не должно расти с количеством стримов). Плохо делать системный класс слишком уж умным. Код должен быть один и чтобы он управлял всеми стримами. aspirant Я помню о настраиваемости.  Пока в черновом варианте я передаю путь к файлу, чтобы сразу можно было протестировать логику подключения, опроса, получения сообщений и т.д.
 С метаданными такая вещь: стримы в Плазе настраиваются из файлов, даже по умолчанию (методы TableSet.InitFromIni / TableSet.InitFromIni2).  Если передавать классу PlazaStream в конструкторе PlazaTable, тогда внутри PlazaStream некий класс TableConfigParser должен будет генерить файл с нужной схемой, чтобы передать ее TableSet.InitFromIni.  Здесь такой момент: предлагаю в SpecialFolder.ApplicationData создать путь Stocksharp\PlazaTrader\Scheme, в котором хранить свои конфиг-схемы-файлы или их создавать в папке TEMP.  Создавать их в подпапке самой Плазы не стоит: требуется админский доступ.
 
 В папке самого плаза шлюза вообще лучше ничего не править. По умолчанию лучше создавать пути в текущем каталоге (я думаю большинству этого будет достаточно). Плюс сделать путь настраиваемым. Вообщем, логика мне виделась такая (если такое невозможно, то поправьте): 
 Создание PlazaTrader.
Опционально. Модификация таблиц с метаданными.
PlazaTrader.Connect.
 
 Проверка, есть ли ini файлы, соответствующие запрашиваемым метаданным.
Если нет, то они создаются на основе PlazaTable.
Есть, но с другими полями, то модифицируются.
Подключение к Плазе и запуск вечного цикла.
 aspirant Чтобы понимать в будущем, в каких случаях мы выкидываем PlazaException?
 
 Только когда приходит плазовская ошибка (заявки, потоки или еще что). aspirant Насколько я понял, есть два варианта:
 
 Одна особенность, все форматирование лучше помещать в PlazaFormatter. Потому как он уже используется для .NET -> Plaza при отправке транзакций. Не плохо было бы туда поместить и обратную трансформацию. aspirant На мой взгляд вызовы GetValAsХХХ(string fieldName) / GetValAsХХХByIndex(uint fieldIndex) нужно реализовать внутри PlazaStream, а мне чтобы дальше писать это класс нужно понимать:  PlazaStream - это служебный класс, или им смогут пользоваться клиенты (читай, сторонние разработчики, использующие PlazaTrader)?
В каком виде выдавать данные классам, которые будут использовать PlazaStream? Через события по одной строчке с конвертацией CP2Record в массив object'ов? Или попробовать сделать что-то типа реализации интерфейса IDataReader с использованием CP2DataBufferClass?
 1. Считаю, что нужно сделать внутренним, до тех пор, пока не попросят вынуть его наружу.[smile]  2. А нельзя просто выбрать данные в коллекцию и передавать уже ввиде родной .NET коллекции? aspirant И последнее насчет фильтрации данных в потоке. Есть предложение это тоже сделать внутри PlazaStream. Тогда при конвертации данных с помощью GetValAsХХХ() / GetValAsХХХByIndex() можно будет проверять только колонки, по которым идет фильтрация, и, если запись не подходит, не выдавать ее клиентскому коду.
 Насчет оптимизации согласен, но опять получается ситуация со слишком умным PlazaStream.
			
			
			
			
		
 | 
			
				|  | 
	
		| Thanks: |   |  | 
			
				|  | 
		
			| 
 | 
		
			
				| Mikhail Sukhov 
 
   
 
						
						
					 | Date: 1/24/2011 
 
 
	
			aspirant Вчера разбирался со схемами таблиц потоков. Хочу выложить мои соображения:
 Да, с точностью получился косяк. Надо исправлять.skuvv , вы все еще на метаданных? Тогда не пропустите момент, который указал aspirant .
			
			
			
			
		
 | 
			
				|  | 
	
		| Thanks: |   |  | 
			
				|  | 
		
			| 
 | 
		
			
				| skuvv 
 
   
 
						
						
					 | Date: 1/24/2011 
 
 
	
			Mikhail Sukhov aspirant Вчера разбирался со схемами таблиц потоков. Хочу выложить мои соображения:
 Да, с точностью получился косяк. Надо исправлять.skuvv , вы все еще на метаданных? Тогда не пропустите момент, который указал aspirant . Добавил для всех сделанных мета-таблиц соответствующий PlazaType для decemical и string
			
			
			
			
		
 | 
			
				|  | 
	
		| Thanks: |   |  | 
			
				|  | 
		
			| 
 | 
		
			
				| aspirant 
 
   
 
						
						
					 | Date: 1/24/2011 
						
							|  |  |  |   |  
 
 
	
			Mikhail Sukhov Вообщем, логика мне виделась такая (если такое невозможно, то поправьте): Создание PlazaTrader.
Опционально. Модификация таблиц с метаданными.
PlazaTrader.Connect.
 
 Проверка, есть ли ini файлы, соответствующие запрашиваемым метаданным.
Если нет, то они создаются на основе PlazaTable.
Есть, но с другими полями, то модифицируются.
Подключение к Плазе и запуск вечного цикла.
 Этап 2 (опционально): создание таблиц PlazaTable кодом клиента (либо нужный набор колонок, либо все) + наш код парсит все ini файлов в заданной директории для создании на их основе таблиц PlazaTable (через метод PlazaTableSerializer.Deserialize(string fileName) + отслеживаем изменения/добавления файлов в этой директории.  Здесь, кстати, уточнение: в предыдущем посте я был не прав.  вот, что написано в документации (P2ClientGate.doc стр. 18): "Клиент также может не указывать никакой схемы при открытии потока, в этом случае сервер будет отдавать все данные, которые публикуются в потоке (далее этот режим будет называться «получение данных по схеме сервера»)."  Т.е., если в потоке несколько таблиц, будут выдаваться данные по всем таблицам. Для управления стримами (PlazaStream) я создам PlazaStreamManager, который будет внутри себя создавать стримы, подписываться на их события и управлять их подключением / отключением (т.е. внутри него будет бесконечный цикл).  В PlazaStreamManager код пользователя передает коллекцию таблиц (по одной или сразу IEnumerable<PlazaTable>) из предыдущего пункта. Этап 3 (PlazaTrader.Connect): если в PlazaStreamManager есть стримы, запускаем его.  Все стримы будут вертеться в одном потоке (thread). Как дополнительную опцию (третьестепенная / четвертостепенная задача), добавить возможность создания приоритетных стримов в отдельном потоке (thread).  Не знаю, нужно ли это? Mikhail Sukhov 2. А нельзя просто выбрать данные в коллекцию и передавать уже ввиде родной .NET коллекции?
 
 Насколько я понял, принцип работы со стримами в Плазе следующий: создаем и инициализируем CP2DataStream, затем CP2TableSet (у каждого стрима только один CP2TableSet). Далее подписываемся на события, открываем стрим.  После "рукопожатия" (StreamLifeNumChanged) приходит событие StreamDataBegin - данные пошли. Они идут через StreamDataInserted по одной строке.  Когда некий объем данных заканчивается, приходит StreamDataEnd.  Мне интересно, как часто Plaza выдает событие StreamDataEnd.  Хочу в ближайшие пару дней запустить какую-нибудь тестовую программу на пару часов и посмотреть.  Если прерывания случаются часто, то действительно можно копить строки (записи) в PlazaStreamManager и выдавать клиенту, например, DataTable или DataRow[] и т.д.  Вместе с этим, мне кажется, нужно дать возможность клиенту тоже получать наш вариант StreamDataInserted, тем более что кроме него там еще есть StreamDataUpdated и StreamDataDeleted.  В этих событиях можно через PlazaFormatter конвертировать данные в .Net'овские, помещать их в List<object> и выдавать последний клиенту, как object[]. Последнее, насчет фильтрации.  Можно будет предусмотреть некий интерфейс IPlazaFilter с методом bool Validate(CP2Record rec, + что-нибудь еще).  В методе PlazaStreamManager, который создает новый стрим, можно передавать IEnumerable<IPlazaFilter> или null, который будет привязываться к конкретному стриму.  Тогда PlazaStreamManager будет перебирать для каждого стрима его IEnumerable<IPlazaFilter> в событиях StreamDataInserted / StreamDataUpdated / StreamDataDeleted, и если какой-то IPlazaFilter возвращает false, не выдавать событие с данными клиенту.
			
			
			
			
		
 | 
			
				|  | 
	
		| Thanks: |   |  | 
			
				|  | 
		
			| 
 | 
		
			
				| aspirant 
 
   
 
						
						
					 | Date: 1/24/2011 
 
 
	
			skuvv Mikhail Sukhov aspirant Вчера разбирался со схемами таблиц потоков. Хочу выложить мои соображения:
 Да, с точностью получился косяк. Надо исправлять.skuvv , вы все еще на метаданных? Тогда не пропустите момент, который указал aspirant . Добавил для всех сделанных мета-таблиц соответствующий PlazaType для decemical и string Круто[biggrin]. Я только собрался писать об этом изменении.  Даже сам еще свои таблицы не исправил.
			
			
			
			
		
 | 
			
				|  | 
	
		| Thanks: |   |  | 
			
				|  | 
		
			| 
 | 
		
			
				| aspirant 
 
   
 
						
						
					 | Date: 1/29/2011 
						
							|  |  |  |   |  
 
 
	
			Только что залил изменения.  Хотел поделиться промежуточными итогами: В класс PlazaColumns добавил три поля:ReplicationStream ReplicationStream { get; }
 string Table { get; }
 ReplicationScheme ReplicationScheme { get; }
 Пока сделал их все virtual, чтобы код компилировался, но вообще первые два поля должны быть abstract, чтобы все классы-наследники их переписали для себя.  Правильные объявления я пока закомментил.  Эти три поля часть метаданных (у каждого наследника PlazaColumns может быть только один набор значений ReplicationStream - ReplicationScheme - Table) и нужны для инициализации PlazaTable, чтобы потом можно его было передать в PlazaStream или просто сохранить на диск через PlazaTableSerializer.
 
Написал первый вариант PlazaStreamManager: пока только создает / удаляет объекты PlazaStream и перехватывает их события.  Весь "ум" из класса PlazaStream убрал.  Теперь это по сути обертка для CP2DataStreamClass.  Его нужно будет протестировать со всеми наследниками наследника PlazaColumns на предмет правильности описания метаданных.  Я его тестировал с PlazaRtsIndexColumns и еще парой классов.  Кстати, при запуске метода Start() PlazaStreamManager начинает заметно подтормаживать GUI-поток .Net'овскго тестового проекта.
Получение данных пока только получалось тестировать после работы: приходит сразу некая порция строк плазовского потока репликации и все.  Днем один раз получилось запустить PlazaStream + PlazaRtsIndexColumns: данные сыпались непрерывно где-то минут пять точно, потом мне нужно было идти.
 Хотелось получить ваши комментарии, рекомендации и т.д., после чего продолжу работу на PlazaStreamManager.  Там еще полно дел.   Кроме того еще нужно дописать PlazaTableSerializer.
			
			
			
			
		
 | 
			
				|  | 
	
		| Thanks: |   |  | 
			
				|  | 
		
			| 
 | 
		
			
				| aspirant 
 
   
 
						
						
					 | Date: 1/29/2011 
 
 
	
			Кстати, только что заметил, что мой PlazaRtsIndexColumns дублируется с PlazaIndexColumns.  Сейчас удалю свое детище[sad]
			
			
			
			
		
 | 
			
				|  | 
	
		| Thanks: |   |  | 
			
				|  | 
		
			| 
 | 
		
			
				| skuvv 
 
   
 
						
						
					 | Date: 1/30/2011 
 
 
	
			Добавил класс с кодами ошибок плазы - PlazaErrorsпарсит код ошибки и возвращает текст
 ps ктото начал заниматься ошибками - пользуйтесь
 | 
			
				|  | 
	
		| Thanks: |   |  | 
			
				|  | 
		
			| 
 | 
		
			
				| Mikhail Sukhov 
 
   
 
						
						
					 | Date: 1/30/2011 
 
 
	
			aspirant Кстати, только что заметил, что мой PlazaRtsIndexColumns дублируется с PlazaIndexColumns.  Сейчас удалю свое детище[sad] А csproj до сих пор на него ссылается. Коммитить нужно все атомарно.
			
			
			
			
		
 | 
			
				|  | 
	
		| Thanks: |   |  | 
			
				|  | 
		
			| 
 | 
		
			
				| Mikhail Sukhov 
 
   
 
						
						
					 | Date: 1/30/2011 
						
							|  |  |  |   |  
 
 
	
			aspirant Хотелось получить ваши комментарии, рекомендации и т.д., после чего продолжу работу на PlazaStreamManager.  Там еще полно дел.   Кроме того еще нужно дописать PlazaTableSerializer.
 
 1. Плохой код. Codetry{
 _dataStream.Close();
 }
 catch (System.Runtime.InteropServices.COMException e)
 {
 // Исправить обработку исключения
 System.Diagnostics.Trace.WriteLine("Exception {0:X}: {1}".Put(e.ErrorCode, e.Message));
 }
 Исключения нужно перехватывать как можно выше. Кто будет вызывать Close, тот пусть и этим занимается. А так ошибка просто проглотиться. 3.  Code_dataStream.TableSet.set_rev(plazaTable.Name, _currentRevision++);  Это меняется на более элегантное, как подсказал R#: Code_dataStream.TableSet.rev[plazaTable.Name] = _currentRevision++; 4. ReplicationStream и ReplicationScheme явно как то не так используется. Это же уровень метаданных, а именно таблица PlazaTable (таблица олицетворяет стрим данных, PlazaStream по этом олицетворению производит подключение). А получилось так, что эти два перечисления размазались по всем практически классам в Плазе. Нехорошо. Конструктора PlazaStream(PlazaTable plazaTable, TRequestType requestType) более чем достаточно. Зачем нужен еще один я не понял. 5. public void AddStream(string key, PlazaColumns schema, IEnumerable<PlazaColumn> columns) Выглядит как то не так. Зачем столько аргументов? Можно же ведь передать один PlazaTable и уже по нему создать стрим, и уже оперировать им в дальнейшем.
			
			
			
			
		
 | 
			
				|  | 
	
		| Thanks: |   |  | 
			
				|  |