CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

Views: 418346
1
<Chapter Label="ClientFunctionality">
2
<Heading>Client's functionality</Heading>
3
4
Sending and getting requests to the &SCSCP; server(s),
5
the client operates with processes. Process is an abstraction
6
which in other words may be also called a remote task. It encapsulates
7
an input/output TCP stream (see <Ref Filt="IsInputOutputTCPStream" />)
8
from the client to the server and the process ID of the CAS running
9
as a server (deduced from the connection initiation message; may be
10
unassigned, if the server CAS did not communicate it).
11
<P/>
12
There are two ways to create processes. One of them is to specify
13
the hostname and port where the &SCSCP; server is running; in this
14
case a new input/output TCP stream will be created. Another way is
15
first to establish the connection with the &SCSCP; server using
16
<Ref Func="NewSCSCPconnection" /> and then keep it alive across
17
multiple remote procedure calls, thus saving time on the DNS lookup
18
and connection initiation. This may give a good speedup in computations
19
with an intensive message exchange. Note that as long as such connection
20
is open, other &SCSCP; clients will not be able to get through, so
21
if several clients are interchanging with the &SCSCP; server at the
22
same time, they should not block each other with long-lasting connections.
23
24
25
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
26
27
<Section Label="SCSCP Connections">
28
<Heading>&SCSCP; connections</Heading>
29
30
<#Include Label="IsSCSCPconnection"/>
31
<#Include Label="NewSCSCPconnection"/>
32
<#Include Label="CloseSCSCPconnection"/>
33
34
</Section>
35
36
37
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
38
39
<Section Label="Client">
40
<Heading>Processes</Heading>
41
42
<#Include Label="IsProcess"/>
43
<#Include Label="NewProcess"/>
44
<#Include Label="CompleteProcess"/>
45
<#Include Label="TerminateProcess"/>
46
47
</Section>
48
49
50
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
51
52
<Section Label="All-in-one">
53
<Heading>All-in-one tool: sending request and getting result</Heading>
54
55
<#Include Label="EvaluateBySCSCP"/>
56
57
Now we demonstrate the procedure <C>GroupIdentificationService</C>,
58
also given in the previous chapter:
59
60
<Example>
61
<![CDATA[
62
gap> G:=SymmetricGroup(4);
63
Sym( [ 1 .. 4 ] )
64
gap> gens:=GeneratorsOfGroup(G);
65
[ (1,2,3,4), (1,2) ]
66
gap> EvaluateBySCSCP( "GroupIdentificationService", [ gens ],
67
> "localhost", 26133 : debuglevel:=3 );
68
rec( attributes := [ [ "call_id", "localhost:26133:2442:xOilXtnw" ],
69
[ "info_runtime", 4 ], [ "info_memory", 2596114432 ],
70
[ "info_message", "Memory usage for the result is 48 bytes" ] ],
71
object := [ 24, 12 ] )
72
]]>
73
</Example>
74
75
Service provider may suggest to the client to use a counterpart function
76
77
<Example>
78
<![CDATA[
79
gap> IdGroupWS := function( G )
80
> local H, result;
81
> if not IsPermGroup(G) then
82
> H:= Image( IsomorphismPermGroup( G ) );
83
> else
84
> H := G;
85
> fi;
86
> result := EvaluateBySCSCP ( "GroupIdentificationService",
87
> [ GeneratorsOfGroup(H) ], "localhost", 26133 );
88
> return result.object;
89
> end;;
90
]]>
91
</Example>
92
93
which works exactly like <Ref BookName="ref" Func="IdGroup" />:
94
95
<Example>
96
<![CDATA[
97
gap> G:=DihedralGroup(64);
98
<pc group of size 64 with 6 generators>
99
gap> IdGroupWS(G);
100
[ 64, 52 ]
101
]]>
102
</Example>
103
104
</Section>
105
106
107
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
108
109
<Section Label="BinaryVsXML">
110
<Heading>Switching between Binary and XML &OpenMath; Encodings</Heading>
111
112
<#Include Label="SwitchSCSCPmodeToBinary"/>
113
114
For example, let us create a vector over <M>GF(3)</M>:
115
<Example>
116
<![CDATA[
117
gap> x := [ Z(3)^0, Z(3), 0*Z(3) ];
118
[ Z(3)^0, Z(3), 0*Z(3) ]
119
]]>
120
</Example>
121
The XML &OpenMath; encoding of such objects is quite bulky:
122
<Example>
123
<![CDATA[
124
gap> OMString( x );
125
"<OMOBJ xmlns=\"http://www.openmath.org/OpenMath\" version=\"2.0\"> <OMA> <OMS\
126
cd=\"list1\" name=\"list\"/> <OMA> <OMS cd=\"arith1\" name=\"power\"/> <OMA> \
127
<OMS cd=\"finfield1\" name=\"primitive_element\"/> <OMI>3</OMI> </OMA> <OMI>0<\
128
/OMI> </OMA> <OMA> <OMS cd=\"arith1\" name=\"power\"/> <OMA> <OMS cd=\"finfiel\
129
d1\" name=\"primitive_element\"/> <OMI>3</OMI> </OMA> <OMI>1</OMI> </OMA> <OMA\
130
> <OMS cd=\"arith1\" name=\"times\"/> <OMA> <OMS cd=\"finfield1\" name=\"primi\
131
tive_element\"/> <OMI>3</OMI> </OMA> <OMI>0</OMI> </OMA> </OMA> </OMOBJ>"
132
gap> Length( OMString(x) );
133
507
134
]]>
135
</Example>
136
We call the &SCSCP; procedure <C>Identity</C> just to test how this object
137
may be sent back and forth. The total length of the procedure call message
138
is 969 symbols:
139
<Log>
140
<![CDATA[
141
gap> SetInfoLevel(InfoSCSCP,3);
142
gap> EvaluateBySCSCP("Identity",[x],"localhost",26133);
143
#I Creating a socket ...
144
#I Connecting to a remote socket via TCP/IP ...
145
#I Got connection initiation message
146
#I <?scscp service_name="GAP" service_version="4.dev" service_id="localhost:2\
147
6133:42448" scscp_versions="1.0 1.1 1.2 1.3" ?>
148
#I Requesting version 1.3 from the server ...
149
#I Server confirmed version 1.3 to the client ...
150
#I Composing procedure_call message:
151
<?scscp start ?>
152
<OMOBJ xmlns="http://www.openmath.org/OpenMath" version="2.0">
153
<OMATTR>
154
<OMATP>
155
<OMS cd="scscp1" name="call_id"/>
156
<OMSTR>localhost:26133:42448:IOs9ZkBU</OMSTR>
157
<OMS cd="scscp1" name="option_return_object"/>
158
<OMSTR></OMSTR>
159
</OMATP>
160
<OMA>
161
<OMS cd="scscp1" name="procedure_call"/>
162
<OMA>
163
<OMS cd="scscp_transient_1" name="Identity"/>
164
<OMA>
165
<OMS cd="list1" name="list"/>
166
<OMA>
167
<OMS cd="arith1" name="power"/>
168
<OMA>
169
<OMS cd="finfield1" name="primitive_element"/>
170
<OMI>3</OMI>
171
</OMA>
172
<OMI>0</OMI>
173
</OMA>
174
<OMA>
175
<OMS cd="arith1" name="power"/>
176
<OMA>
177
<OMS cd="finfield1" name="primitive_element"/>
178
<OMI>3</OMI>
179
</OMA>
180
<OMI>1</OMI>
181
</OMA>
182
<OMA>
183
<OMS cd="arith1" name="times"/>
184
<OMA>
185
<OMS cd="finfield1" name="primitive_element"/>
186
<OMI>3</OMI>
187
</OMA>
188
<OMI>0</OMI>
189
</OMA>
190
</OMA>
191
</OMA>
192
</OMA>
193
</OMATTR>
194
</OMOBJ>
195
<?scscp end ?>
196
#I Total length 969 characters
197
...
198
rec( attributes := [ [ "call_id", "localhost:26133:42448:IOs9ZkBU" ] ],
199
object := [ Z(3)^0, Z(3), 0*Z(3) ] )
200
]]>
201
</Log>
202
Now we switch to binary mode:
203
<Log>
204
<![CDATA[
205
gap> SwitchSCSCPmodeToBinary();
206
gap> EvaluateBySCSCP("Identity",[x],"localhost",26133);
207
#I Creating a socket ...
208
#I Connecting to a remote socket via TCP/IP ...
209
#I Got connection initiation message
210
#I <?scscp service_name="GAP" service_version="4.dev" service_id="localhost:2\
211
6133:42448" scscp_versions="1.0 1.1 1.2 1.3" ?>
212
#I Requesting version 1.3 from the server ...
213
#I Server confirmed version 1.3 to the client ...
214
#I Composing procedure_call message:
215
3C3F7363736370207374617274203F3E0A18121408060773637363703163616C6C5F6964061E6C\
216
6F63616C686F73743A32363133333A34323434383A3256675A5562755A0806147363736370316F\
217
7074696F6E5F72657475726E5F6F626A6563740600151008060E73637363703170726F63656475\
218
72655F63616C6C1008110873637363705F7472616E7369656E745F314964656E74697479100805\
219
046C697374316C69737410080605617269746831706F7765721008091166696E6669656C643170\
220
72696D69746976655F656C656D656E7401031101001110080605617269746831706F7765721008\
221
091166696E6669656C64317072696D69746976655F656C656D656E740103110101111008060561\
222
726974683174696D65731008091166696E6669656C64317072696D69746976655F656C656D656E\
223
7401031101001111111113193C3F736373637020656E64203F3E0A
224
#I Total length 339 bytes
225
#I Request sent ...
226
#I Waiting for reply ...
227
#I <?scscp start ?>
228
#I Got back: object [ Z(3)^0, Z(3), 0*Z(3) ] with attributes
229
[ [ "call_id", "localhost:26133:42448:2VgZUbuZ" ] ]
230
rec( attributes := [ [ "call_id", "localhost:26133:42448:2VgZUbuZ" ] ],
231
object := [ Z(3)^0, Z(3), 0*Z(3) ] )
232
gap> SetInfoLevel(InfoSCSCP,3);
233
]]>
234
</Log>
235
As we can see, the size of the message is almost three times shorter, and
236
this is not the limit. Switching to binary &OpenMath; encoding in
237
combination with pickling and unpickling from &IO; package (see in the last
238
Chapter) and special methods for pickling compressed vectors implemented
239
in the <Package>Cvec</Package> available in &GAP;&nbsp;4.5 allow to
240
dramatically reduce the overhead for vectors and matrices over finite
241
fields, making a roundtrip up to a thousand times faster.
242
243
</Section>
244
245
246
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
247
248
<Section Label="Remote">
249
<Heading>Remote objects</Heading>
250
251
The &SCSCP; package introduces new kind of objects - <E>remote objects</E>.
252
They provide an opportunity to manipulate with objects on remote services
253
without their actual transmitting over the network. Remote objects store
254
the information that allows to access the original object: the server name
255
and the port number through which the object can be accessed, and the variable
256
name under which it is stored in the remote system. Two remote objects are
257
equal if and only if all these three parameters coincide.
258
<P/>
259
260
There are two types of remote object which differ by their lifetime:
261
<List>
262
<Item>temporary remote objects which exist only within a single session;</Item>
263
<Item>persistent remote objects which stay alive across multiple sessions.</Item>
264
</List>
265
266
First we show the example of the temporary remote object in a session. The
267
procedure <C>PointImages</C> returns the set of images of a point <M>i</M>
268
under the generators of the group <M>G</M>. First we create the symmetric
269
group <M>S_3</M> on the client and store it remotely on the server
270
(call 1), then we compute set of images for <M>i=1,2</M> (calls 2,3) and
271
finally demonstrate that we may retrieve the group from the server (call 4):
272
273
<Example>
274
<![CDATA[
275
gap> stream:=InputOutputTCPStream( "localhost", 26133 );
276
< input/output TCP stream to localhost:26133 >
277
gap> StartSCSCPsession(stream);
278
"localhost:26133:6184"
279
gap> OMPutProcedureCall( stream, "store_session",
280
> rec( object := [ SymmetricGroup(3) ],
281
> attributes := [ [ "call_id", "1" ],
282
> ["option_return_cookie"] ] ) );
283
true
284
gap> SCSCPwait( stream );
285
gap> G:=OMGetObjectWithAttributes( stream ).object;
286
< remote object scscp://localhost:26133/TEMPVarSCSCPo3Bc8J75 >
287
gap> OMPutProcedureCall( stream, "PointImages",
288
> rec( object := [ G, 1 ],
289
> attributes := [ [ "call_id", "2" ] ] ) );
290
true
291
gap> SCSCPwait( stream );
292
gap> OMGetObjectWithAttributes( stream );
293
rec( attributes := [ [ "call_id", "2" ] ], object := [ 2 ] )
294
gap> OMPutProcedureCall( stream, "PointImages",
295
> rec( object := [ G, 2 ],
296
> attributes := [ [ "call_id", "3" ] ] ) );
297
true
298
gap> SCSCPwait( stream );
299
gap> OMGetObjectWithAttributes( stream );
300
rec( attributes := [ [ "call_id", "3" ] ], object := [ 1, 3 ] )
301
gap> OMPutProcedureCall( stream, "retrieve",
302
> rec( object := [ G ],
303
> attributes := [ [ "call_id", "4" ] ] ) );
304
true
305
gap> SCSCPwait( stream );
306
gap> OMGetObjectWithAttributes( stream );
307
rec( attributes := [ [ "call_id", "4" ] ],
308
object := Group([ (1,2,3), (1,2) ]) )
309
gap> CloseStream(stream);
310
]]>
311
</Example>
312
313
After the stream is closed, it is no longer possible to retrieve the
314
group <M>G</M> again or use it as an argument.
315
<P/>
316
317
Thus, the usage of remote objects existing during a session reduces the
318
network traffic, since we pass only references instead of actual &OpenMath;
319
representation of an object. Also, the remote object on the server may
320
accumulate certain information in its properties and attributes, which may
321
not be included in it default &OpenMath; representation.
322
<P/>
323
324
Now we show remote objects which remain alive after the session is
325
closed. Such remote objects may be accessed later, for example, by:
326
<List>
327
<Item>subsequent procedure calls from the same instance of &GAP; or another system;</Item>
328
<Item>other instances of &GAP; or another systems (if the identifier of an object is known)</Item>
329
<Item>another &SCSCP; servers which obtained a reference to such object as an argument of a procedure call.</Item>
330
</List>
331
332
<#Include Label="StoreAsRemoteObject"/>
333
334
Internally, the remote object carries all the information which is required
335
to get access to the original object: its identifier, server and port:
336
337
<Example>
338
<![CDATA[
339
gap> s![1];
340
"TEMPVarSCSCPLvIUUtL3"
341
gap> s![2];
342
"localhost"
343
gap> s![3];
344
26133
345
]]>
346
</Example>
347
348
When the remote object is printed in the &OpenMath; format, we
349
use symbols <C>@</C> and <C>:</C> to combine these parameters
350
in the &OpenMath; reference:
351
352
<Example>
353
<![CDATA[
354
gap> OMPrint(s);
355
<OMOBJ>
356
<OMR href="scscp://localhost:26133/TEMPVarSCSCPLvIUUtL3" />
357
</OMOBJ>
358
]]>
359
</Example>
360
361
This allows substitution of remote object as arguments into procedure calls
362
in the same manner like we do this with usual objects:
363
364
<Example>
365
<![CDATA[
366
gap> EvaluateBySCSCP("WS_IdGroup",[s],"localhost",26133);
367
rec( attributes := [ [ "call_id", "localhost:26133:52918:Viq6EWBP" ] ],
368
Line 183 :
369
object := [ 6, 1 ] )
370
]]>
371
</Example>
372
373
<#Include Label="IsRemoteObject"/>
374
<#Include Label="RemoteObjectsFamily"/>
375
<#Include Label="RetrieveRemoteObject"/>
376
<#Include Label="UnbindRemoteObject"/>
377
378
Finally, we show an example when first we create a group on the service
379
running on port 26133, and then identify it on the service running on port
380
26134:
381
<Example>
382
<![CDATA[
383
gap> s:=StoreAsRemoteObject( SymmetricGroup(3), "localhost", 26133 );
384
< remote object scscp://localhost:26133/TEMPVarSCSCPNqc8Bkan >
385
gap> EvaluateBySCSCP( "WS_IdGroup", [ s ], "localhost", 26134 );
386
rec( object := [ 6, 1 ], attributes := [ [ "call_id", "localhost:26134:7414" ] ] )
387
]]>
388
</Example>
389
Instead of transmitting the group to the client and then sending it
390
as an argument to the second service, the latter service directly
391
retrieves the group from the first service:
392
<Example>
393
<![CDATA[
394
gap> EvaluateBySCSCP("WS_IdGroup",[s],"localhost",26133 : output:="cookie" );
395
rec( attributes := [ [ "call_id", "localhost:26133:52918:mRU6w471" ] ],
396
object := < remote object scscp://localhost:26133/TEMPVarSCSCPS9SVe9PZ > )
397
]]>
398
</Example>
399
400
</Section>
401
402
</Chapter>
403