23 """ |
23 """ |
24 Class implementing the main part of the background client. |
24 Class implementing the main part of the background client. |
25 """ |
25 """ |
26 def __init__(self, host, port, maxProcs): |
26 def __init__(self, host, port, maxProcs): |
27 """ |
27 """ |
28 Constructor of the BackgroundClient class. |
28 Constructor |
29 |
29 |
30 @param host ip address the background service is listening |
30 @param host ip address the background service is listening |
31 @type str |
31 @type str |
32 @param port port of the background service |
32 @param port port of the background service |
33 @type int |
33 @type int |
45 |
45 |
46 def __initClientService(self, fn, path, module): |
46 def __initClientService(self, fn, path, module): |
47 """ |
47 """ |
48 Private method to import the given module and register it as service. |
48 Private method to import the given module and register it as service. |
49 |
49 |
50 @param fn service name to register (str) |
50 @param fn service name to register |
51 @param path contains the path to the module (str) |
51 @type str |
52 @param module name to import (str) |
52 @param path contains the path to the module |
53 @return text result of the import action (str) |
53 @type str |
|
54 @param module name to import |
|
55 @type str |
|
56 @return text result of the import action |
|
57 @rtype str |
54 """ |
58 """ |
55 sys.path.insert(1, path) |
59 sys.path.insert(1, path) |
56 try: |
60 try: |
57 importedModule = __import__(module, globals(), locals(), [], 0) |
61 importedModule = __import__(module, globals(), locals(), [], 0) |
58 self.services[fn] = importedModule.initService() |
62 self.services[fn] = importedModule.initService() |
66 except ImportError: |
70 except ImportError: |
67 return 'Import Error' |
71 return 'Import Error' |
68 |
72 |
69 def __send(self, fx, fn, data): |
73 def __send(self, fx, fn, data): |
70 """ |
74 """ |
71 Private method to send a job response back to the BackgroundService. |
75 Private method to send a job response back to the BackgroundService |
72 |
76 server. |
73 @param fx remote function name to execute (str) |
77 |
74 @param fn filename for identification (str) |
78 @param fx remote function name to execute |
75 @param data return value(s) (any basic datatype) |
79 @type str |
|
80 @param fn filename for identification |
|
81 @type str |
|
82 @param data return value(s) |
|
83 @type any basic datatype |
76 """ |
84 """ |
77 if not isinstance(data, ( |
85 if not isinstance(data, ( |
78 dict, list, tuple, str, int, float, bool, type(None), |
86 dict, list, tuple, str, int, float, bool, type(None), |
79 )): |
87 )): |
80 # handle sending of objects of unsupported types |
88 # handle sending of objects of unsupported types |
87 self.connection.sendall(header) |
95 self.connection.sendall(header) |
88 self.connection.sendall(packedData) |
96 self.connection.sendall(packedData) |
89 |
97 |
90 def __receive(self, length): |
98 def __receive(self, length): |
91 """ |
99 """ |
92 Private methode to receive the given length of bytes. |
100 Private method to receive the given length of bytes. |
93 |
101 |
94 @param length bytes to receive (int) |
102 @param length bytes to receive |
95 @return received bytes or None if connection closed (bytes) |
103 @type int |
|
104 @return received bytes or None if connection closed |
|
105 @rtype bytes |
96 """ |
106 """ |
97 data = b'' |
107 data = b'' |
98 while len(data) < length: |
108 while len(data) < length: |
99 newData = self.connection.recv(length - len(data)) |
109 newData = self.connection.recv(length - len(data)) |
100 if not newData: |
110 if not newData: |
102 data += newData |
112 data += newData |
103 return data |
113 return data |
104 |
114 |
105 def __peek(self, length): |
115 def __peek(self, length): |
106 """ |
116 """ |
107 Private methode to peek the given length of bytes. |
117 Private method to peek the given length of bytes. |
108 |
118 |
109 @param length bytes to receive (int) |
119 @param length bytes to receive |
110 @return received bytes (bytes) |
120 @type int |
|
121 @return received bytes |
|
122 @rtype bytes |
111 """ |
123 """ |
112 data = b'' |
124 data = b'' |
113 self.connection.setblocking(False) |
125 self.connection.setblocking(False) |
114 try: |
126 try: |
115 data = self.connection.recv(length, socket.MSG_PEEK) |
127 data = self.connection.recv(length, socket.MSG_PEEK) |
122 |
134 |
123 def __cancelled(self): |
135 def __cancelled(self): |
124 """ |
136 """ |
125 Private method to check for a job cancellation. |
137 Private method to check for a job cancellation. |
126 |
138 |
127 @return flag indicating a cancellation (boolean) |
139 @return flag indicating a cancellation |
|
140 @rtype bool |
128 """ |
141 """ |
129 msg = self.__peek(struct.calcsize(b'!II') + 6) |
142 msg = self.__peek(struct.calcsize(b'!II') + 6) |
130 if msg[-6:] == b"CANCEL": |
143 if msg[-6:] == b"CANCEL": |
131 # get rid of the message data |
144 # get rid of the message data |
132 self.__receive(struct.calcsize(b'!II') + 6) |
145 self.__receive(struct.calcsize(b'!II') + 6) |
203 self.connection.shutdown(socket.SHUT_RDWR) |
216 self.connection.shutdown(socket.SHUT_RDWR) |
204 self.connection.close() |
217 self.connection.close() |
205 |
218 |
206 if __name__ == '__main__': |
219 if __name__ == '__main__': |
207 if len(sys.argv) != 4: |
220 if len(sys.argv) != 4: |
208 print('Host, port and max. processes parameters are missing. Abort.') |
221 print('Host, port and max. processes parameters are missing.' |
|
222 ' Aborting.') |
209 sys.exit(1) |
223 sys.exit(1) |
210 |
224 |
211 host, port, maxProcs = sys.argv[1:] |
225 host, port, maxProcs = sys.argv[1:] |
212 backgroundClient = BackgroundClient(host, int(port), int(maxProcs)) |
226 backgroundClient = BackgroundClient(host, int(port), int(maxProcs)) |
213 # Start the main loop |
227 # Start the main loop |