powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Доступ к глобалу из COS по сети.
8 сообщений из 8, страница 1 из 1
Доступ к глобалу из COS по сети.
    #36221613
Hisbreht Victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Возникла ситуация, когда потребовалось реализовать сие без ECP.
Расширенный синтаксис (с указанием сетевого пути к глобалу) работает неустойчиво, часто возвращает ошибку, что глобал занят (что, впрочем, логично).
Использование mdapi (c сайта karataev.nm.ru) позволило решить эту проблему, но работает уж очень медленно.
Оценка времени выполнения кода показала странные результаты. больше всего времени (и очень много по сравнению с другими операциями) занимает первый вызов READ после последнего WRITE.
Причём оценка времени выполнения кода самого mdapi показала, что там задержек между считыванием команды и выдачей ответа нет.
Вопросы такие.
1. откуда могла взяться задержка и можно ли её победить?
2. Есть ли альтернативные методы получения содержимого глобала по сети без использования ECP?

Код процедуры, получающей содержимое узла глобала по сети при помощи mdapi, приведён ниже.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
readexglob(host,globname)
	s glbvalue=""
	S io="|TCP|8738"
	OPEN io:(host::"A"): 2  ;Connect to server
	IF ('$TEST) { 
		Quit ""
	} ELSE { 
	    s writecmd=$c(254)_$c(254)_$c(254)_$c(254)
		USE io:(::"-Q+M") write writecmd
	    s writecmd=$c(2)_$c(3)_$c(0)_$c(4)_$c(1)_$c($L(globname))_$zcvt(globname,"O","CP1251")_$c(1)_$c(0)_$c(0)_$c(3)_$c(0)_$c(0)_$c(0)_$c(0)
		write writecmd,!
    }
    IF ('$TEST) { 
       CLOSE io 
       QUIT ""
    } ELSE {
       READ value# 1 : 5 
       READ value# 4 : 1 
       s svalue= 0 
       READ value# 1 : 1 
       s svalue=svalue+$A(value)
       READ value# 1 : 1 
       s svalue=svalue+($A(value)* 256 )
       READ value# 1 : 1 
       s svalue=svalue+($A(value)* 256 * 256 )
       READ value# 1 : 1 
       s svalue=svalue+($A(value)* 256 * 256 * 256 )
       READ value#svalue: 1 
	   IF ('$TEST) { 
    	   CLOSE io 
       		QUIT ""
	   }
       s ii=0
       f {
	       s ii=ii+1
	       q:ii>value
	 	   READ value1#1:1
    		READ value1#4:1
       s svalue=0
       READ value1#1:1
       s svalue=svalue+$A(value1)
       READ value1#1:1
       s svalue=svalue+($A(value1)*256)
       READ value1#1:1
       s svalue=svalue+($A(value1)*256*256)
       READ value1#1:1
       s svalue=svalue+($A(value1)*256*256*256)
     		READ value1#svalue:1
     		s glbvalue=glbvalue_value1
		    IF ('$TEST) QUIT
       }
    }
    CLOSE io 
	Quit glbvalue

Виктор
...
Рейтинг: 0 / 0
Доступ к глобалу из COS по сети.
    #36222277
Alexey Maslov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Очень странный протокол:
Код: plaintext
1.
2.
3.
4.
5.
       READ value# 1 : 5 
       READ value# 4 : 1 
       s svalue= 0 
       READ value# 1 : 1 
       ...
Читается 1 символ с таймаутом 5 сек, потом еще 4 с таймаутом 1 сек, результат чтения всегда отбрасывается, и только на 3-ем READе началинается чтение полезных данных. Возможность отрицательного результата ('$TEST) никак не учитывается, поэтому, если первый READ не завершится за 5 сек, "в мусор" уйдет часть полезных данных. По-видимому, в этом случае с клиента придет повторный запрос - кто-то же должен все это разруливать... Так что задержки на первом чтении не удивительны.
Альтернативы ECP с аналогичным функционалом и быстродействием, ИМХО, нет, но нечто подобное можно реализовать с помощью %Net.RemoteConnection, написав класс с методом "выдать содержимое узла глобала по имени" и вызывая его удаленно.
Если еще немного подумать :), то станет ясно, что быстрой работы и тут не достичь, т.к. "поузловая" передача глобала заведомо медленнее поблочной. Ср., например, DDP и ECP. Возможно, лучше передавать по несколько узлов за раз и локально их "кэшировать", или в фоне передавать весь глобал по мере его формирования. Последнее возможно с помощью стандартного средства - Shadowing. Подойдет ли что-то из этого, конечно, сильно зависит от задачи.
...
Рейтинг: 0 / 0
Доступ к глобалу из COS по сети.
    #36223414
Valeriu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Использую Activate на клиенте.
На сервере использую COS, функцию Query (не самый быстрый способ ...)
Передаю удаленному клиенту порциями по 1000 узлов (Одномерный масив строк).
Записываю данные на удаленной клиентской машине в простой
текстовый файл (18 Gb) за 1,5 мин ....

Код: plaintext
1.
2.
3.
4.
5.
GlbNodes(Var,Nod,i,Er) ;Loading  1000  Global Nodes 
    Kill Nod
    For i= 1 : 1 : 1000  Set Var=$Q(@Var) Quit:Var=""  Do
    . Set Nod(i)=Var_"="_@Var
    Quit
    ;
...
Рейтинг: 0 / 0
Доступ к глобалу из COS по сети.
    #36223441
Valeriu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Забыл уточнить.
Роль сервера - машина Pentium 4, 2.4 GHz, RAM 512 MB (MSM)
Думаю на приличной Cache' машине, на много быстрее ...
...
Рейтинг: 0 / 0
Доступ к глобалу из COS по сети.
    #36223543
Alexey Maslov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valeriu18 Gb за 1,5 мин Не верю (с)
Код: plaintext
1.
USER>w  18 * 1024 /90_" MB/s"
 204 . 8  MB/s
получается существенно выше скорости, возможной в сети 1000BaseT :)
Но по-любому, если надо передать весь глобал, то сделать это можно весьма быстро. Завтра померю на своем аналогичном софте (удаленный %GOF/%GIF через Factory).
У топикстартера же, если я правильно понял, несколько иная задача: выборочно передавать отдельные узлы глобалов.
...
Рейтинг: 0 / 0
Доступ к глобалу из COS по сети.
    #36224161
Valeriu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
К стати, как раз сеть у меня 100 Mbit/s (100BaseT) ...
Проверил еще раз, результат такой-же. Вот код клиентского приложения на VB:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
Public Sub SaveAll()
Dim Ret1 As String, Er As String, file As String
Dim ret( 6000 ) As String
Dim arrayX As Variant
Dim cnd As Integer, i As Integer, cnt As Integer
Dim Nod As String
Dim rec As Long
Dim Varfull As Variant, schet As Variant, GlobCik As Variant
Dim lvItem As ListItem
Dim FileHandle%
On Error GoTo Error
     MDIFrm.MousePointer = vbHourglass
    Set lvItem = File1.SelectedItem
    MDIFrm.glbname.Text = lvItem.Text
    MDIFrm.txtNod1.Text = lvItem.Text & "("
 If MDIFrm.glbname.Text = "" Then
 MsgBox "Select Global !!!", vbInformation, " Global !!!"
 Exit Sub
 End If
    file = "c:\ret.msm"
    FileHandle% = FreeFile
    Open file For Output As #FileHandle%
    schet =  0 
    For GlobCik =  1  To  100000 
        m.Do "GlbNodes^%ZgnED", MDIFrm.glbname.Text, ret, cnt, Er
        If Er <> "" Then
        MsgBox Er, vbExclamation
        Exit Sub
        End If
        arrayX = ret
            For i =  1  To cnt -  1 
                schet = schet +  1 
                Ret1 = arrayX(i)
                Print #FileHandle%, Ret1
                MDIFrm.glbname.Text = Piece(Ret1, ")=",  1 ) & ")"
            Next i
            If cnt <>  1000  Then ' Ultima portie de "cnt" noduri !!!
            frmGlobEdt.Caption = (GlobCik * 1000) + cnt & " - Total Strings..."
            MsgBox "These are the last " & cnt & " Nodes..."
            Exit For
            Exit Sub
            End If
            'MDIFrm.Paus
            frmGlobEdt.Caption = GlobCik *  1000  & " - Total Strings..."
    Next GlobCik
    Close #FileHandle%
   MDIFrm.MousePointer = vbDefault
Exit Sub
Error:
MDIFrm.MousePointer = vbDefault
MsgBox ("Error: " & Err.Description)

End Sub
...
Рейтинг: 0 / 0
Доступ к глобалу из COS по сети.
    #36224336
Valeriu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прошу меня извинить, я вчера явно заработался ...
Явно ошибка ! Не 18Gb а 18Mgb

Еще раз простите за ошибку ...
...
Рейтинг: 0 / 0
Доступ к глобалу из COS по сети.
    #36225112
Alexey Maslov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вот и результаты экспорта в блочном режиме (Remote %GOF), если кому интересно.
На сервере установлена Cache for UNIX (Red Hat Enterprise Linux for x86-64) 2008.1
и мой пакет %z.GG - Remote %GOF/%GIF, позволяющий выполнять операции блочного экспорта/импорта глобалов на удаленные клиенты. Клиент может быть написан на чем угодно, лишь бы поддерживалась работа с Cache Objects.
Что делать с результатом экспорта, личное дело клиента. Если просто копировать его в файл, получается корректный файл блочного формата Cache (формата %GOF), что, в общем-то, не удивительно :) Поддерживаются длинные строки в данных (до 3.6MB), если позволяет версия Cache и конфигурация сервера.
Работает несколько быстрее, чем сохранение в локальной папке на сервере с последующим копированием на клиент, и в десятки раз быстрее аналогов, работающих на уровне узлов глобалов.
В конкретных условиях:
Сервер: CPU определяется как 2 * Dual-Core AMD Opteron(tm) Processor 2218, RAM 16GB
Клиент: Intel P4/3000MHz, RAM 1GB
Сеть: 100BaseT
были получены результаты: cкорость экспорта: 6.7MB/s, cкорость импорта: 4.9MB/s.
В качестве примера приведу клиентский код экспорта глобалов с удаленного сервера в локальный gof-файл, написанный на JavaScript (для Сервера сценариев Windows v. 5.6).
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
 var shell = WScript.CreateObject("WScript.Shell");
 var fso = WScript.CreateObject("Scripting.FileSystemObject");
 var f = fso.CreateTextFile( "xxxx1.gof", true);
 var pack = ""; var np =  0 ; 
 var gblist = "^zzz";
 var factory = new ActiveXObject("CacheObject.Factory");
 var connStr = factory.connectdlg();

 ok = factory.connect( connStr );
 WScript.echo( "Connected to " + connStr);
 var obj = factory.New("%z.GG");

 var rc = obj.GOFinit(gblist); // иницируем экспорт глобалов, перечисленных в gblist

 WScript.Echo( " GOFinit Status = " + obj.Status + "; Gbls = "+ obj.Gbls + " ; Press Enter to Start" );
 var d = new Date(); var t0 = d.getTime();

 // читаем пакеты и пишем их в файл; пакет длины  0  - признак конца.
 // пакеты имеют фиксированную длину (в текущей версии длина = 16KB)
 do {
   try {
	pack = obj.GOFrpack();
	if (np ==  1 ) var packlen= pack.length;
   } catch (e) {
	WScript.Echo (e.number + " " + e.description);
   }
   if (pack.length !=  0 ) { f.Write( pack );  np++; }
 } while (pack.length);
 var d1 = new Date(); var t1 = d1.getTime();
 WScript.Echo("Finished in " + (t1-t0)/ 1000  +"s; Npackets = " + np + "; V = "+ np*packlen* 1000 /(t1-t0)/ 1024 / 1024  + " MB/s");
 f.Close();
 obj.sys_Close();
 obj = null;
 factory.disconnect();
Если переписать клиента на COS и задействовать %Net.RemoteConnection, можно получить достаточно быстрый инструмент для передачи глобалов между серверами Cache. Альфа-версия уже существует :) Естественно, интереснее будет сразу создавать глобалы в БД, без промежуточной записи в файл.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Доступ к глобалу из COS по сети.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]