/src/imagemagick/MagickCore/distribute-cache.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
3 | | % % |
4 | | % % |
5 | | % DDDD IIIII SSSSS TTTTT RRRR IIIII BBBB U U TTTTT EEEEE % |
6 | | % D D I SS T R R I B B U U T E % |
7 | | % D D I SSS T RRRR I BBBB U U T EEE % |
8 | | % D D I SS T R R I B B U U T E % |
9 | | % DDDDA IIIII SSSSS T R R IIIII BBBB UUU T EEEEE % |
10 | | % % |
11 | | % CCCC AAA CCCC H H EEEEE % |
12 | | % C A A C H H E % |
13 | | % C AAAAA C HHHHH EEE % |
14 | | % C A A C H H E % |
15 | | % CCCC A A CCCC H H EEEEE % |
16 | | % % |
17 | | % % |
18 | | % MagickCore Distributed Pixel Cache Methods % |
19 | | % % |
20 | | % Software Design % |
21 | | % Cristy % |
22 | | % January 2013 % |
23 | | % % |
24 | | % % |
25 | | % Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization % |
26 | | % dedicated to making software imaging solutions freely available. % |
27 | | % % |
28 | | % You may not use this file except in compliance with the License. You may % |
29 | | % obtain a copy of the License at % |
30 | | % % |
31 | | % https://imagemagick.org/script/license.php % |
32 | | % % |
33 | | % Unless required by applicable law or agreed to in writing, software % |
34 | | % distributed under the License is distributed on an "AS IS" BASIS, % |
35 | | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % |
36 | | % See the License for the specific language governing permissions and % |
37 | | % limitations under the License. % |
38 | | % % |
39 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
40 | | % |
41 | | % A distributed pixel cache is an extension of the traditional pixel cache |
42 | | % available on a single host. The distributed pixel cache may span multiple |
43 | | % servers so that it can grow in size and transactional capacity to support |
44 | | % very large images. Start up the pixel cache server on one or more machines. |
45 | | % When you read or operate on an image and the local pixel cache resources are |
46 | | % exhausted, ImageMagick contacts one or more of these remote pixel servers to |
47 | | % store or retrieve pixels. |
48 | | % |
49 | | */ |
50 | | |
51 | | /* |
52 | | Include declarations. |
53 | | */ |
54 | | #include "MagickCore/studio.h" |
55 | | #include "MagickCore/cache.h" |
56 | | #include "MagickCore/cache-private.h" |
57 | | #include "MagickCore/distribute-cache.h" |
58 | | #include "MagickCore/distribute-cache-private.h" |
59 | | #include "MagickCore/exception.h" |
60 | | #include "MagickCore/exception-private.h" |
61 | | #include "MagickCore/geometry.h" |
62 | | #include "MagickCore/image.h" |
63 | | #include "MagickCore/image-private.h" |
64 | | #include "MagickCore/list.h" |
65 | | #include "MagickCore/locale_.h" |
66 | | #include "MagickCore/memory_.h" |
67 | | #include "MagickCore/nt-base-private.h" |
68 | | #include "MagickCore/pixel.h" |
69 | | #include "MagickCore/policy.h" |
70 | | #include "MagickCore/random_.h" |
71 | | #include "MagickCore/registry.h" |
72 | | #include "MagickCore/splay-tree.h" |
73 | | #include "MagickCore/string_.h" |
74 | | #include "MagickCore/string-private.h" |
75 | | #include "MagickCore/utility-private.h" |
76 | | #include "MagickCore/version.h" |
77 | | #include "MagickCore/version-private.h" |
78 | | #undef MAGICKCORE_HAVE_DISTRIBUTE_CACHE |
79 | | #define SOCKET_TYPE int |
80 | | #if defined(MAGICKCORE_DPC_SUPPORT) |
81 | | #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT) |
82 | | #include <netinet/in.h> |
83 | | #include <netdb.h> |
84 | | #include <sys/socket.h> |
85 | | #include <arpa/inet.h> |
86 | 0 | #define CLOSE_SOCKET(socket) (void) close_utf8(socket) |
87 | | #define HANDLER_RETURN_TYPE void * |
88 | 0 | #define HANDLER_RETURN_VALUE (void *) NULL |
89 | 0 | #define SOCKET_TYPE int |
90 | | #define LENGTH_TYPE size_t |
91 | | #define MAGICKCORE_HAVE_DISTRIBUTE_CACHE 1 |
92 | | #elif defined(_MSC_VER) |
93 | | #define CLOSE_SOCKET(socket) (void) closesocket(socket) |
94 | | #define HANDLER_RETURN_TYPE DWORD WINAPI |
95 | | #define HANDLER_RETURN_VALUE 0 |
96 | | #undef SOCKET_TYPE |
97 | | #define SOCKET_TYPE SOCKET |
98 | | #define LENGTH_TYPE int |
99 | | #define MAGICKCORE_HAVE_DISTRIBUTE_CACHE 1 |
100 | | #define MAGICKCORE_HAVE_WINSOCK2 1 |
101 | | #endif |
102 | | #endif |
103 | | |
104 | | /* |
105 | | Define declarations. |
106 | | */ |
107 | 0 | #define DPCHostname "127.0.0.1" |
108 | 0 | #define DPCPendingConnections 10 |
109 | 0 | #define DPCPort 6668 |
110 | | #define DPCSessionKeyLength 8 |
111 | | #ifndef MSG_NOSIGNAL |
112 | | # define MSG_NOSIGNAL 0 |
113 | | #endif |
114 | | |
115 | | /* |
116 | | Static declarations. |
117 | | */ |
118 | | #ifdef MAGICKCORE_HAVE_WINSOCK2 |
119 | | static SemaphoreInfo |
120 | | *winsock2_semaphore = (SemaphoreInfo *) NULL; |
121 | | |
122 | | static WSADATA |
123 | | *wsaData = (WSADATA*) NULL; |
124 | | #endif |
125 | | |
126 | | /* |
127 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
128 | | % % |
129 | | % % |
130 | | % % |
131 | | + A c q u i r e D i s t r i b u t e C a c h e I n f o % |
132 | | % % |
133 | | % % |
134 | | % % |
135 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
136 | | % |
137 | | % AcquireDistributeCacheInfo() allocates the DistributeCacheInfo structure. |
138 | | % |
139 | | % The format of the AcquireDistributeCacheInfo method is: |
140 | | % |
141 | | % DistributeCacheInfo *AcquireDistributeCacheInfo(ExceptionInfo *exception) |
142 | | % |
143 | | % A description of each parameter follows: |
144 | | % |
145 | | % o exception: return any errors or warnings in this structure. |
146 | | % |
147 | | */ |
148 | | |
149 | | #if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) |
150 | | static inline MagickOffsetType dpc_read(SOCKET_TYPE magick_unused(file), |
151 | | const MagickSizeType magick_unused(length), |
152 | | unsigned char *magick_restrict magick_unused(message)) |
153 | | { |
154 | | magick_unreferenced(file); |
155 | | magick_unreferenced(length); |
156 | | magick_unreferenced(message); |
157 | | return(-1); |
158 | | } |
159 | | #else |
160 | | static inline MagickOffsetType dpc_read(SOCKET_TYPE file,const MagickSizeType length, |
161 | | unsigned char *magick_restrict message) |
162 | 0 | { |
163 | 0 | MagickOffsetType |
164 | 0 | i; |
165 | |
|
166 | 0 | ssize_t |
167 | 0 | count; |
168 | |
|
169 | 0 | count=0; |
170 | 0 | for (i=0; i < (MagickOffsetType) length; i+=count) |
171 | 0 | { |
172 | 0 | count=recv(file,(char *) message+i,(LENGTH_TYPE) MagickMin(length- |
173 | 0 | (MagickSizeType) i,(MagickSizeType) MagickMaxBufferExtent),0); |
174 | 0 | if (count <= 0) |
175 | 0 | { |
176 | 0 | count=0; |
177 | 0 | if (errno != EINTR) |
178 | 0 | break; |
179 | 0 | } |
180 | 0 | } |
181 | 0 | return(i); |
182 | 0 | } |
183 | | #endif |
184 | | |
185 | | #if defined(MAGICKCORE_HAVE_WINSOCK2) |
186 | | static void InitializeWinsock2(MagickBooleanType use_lock) |
187 | | { |
188 | | if (use_lock != MagickFalse) |
189 | | { |
190 | | if (winsock2_semaphore == (SemaphoreInfo *) NULL) |
191 | | ActivateSemaphoreInfo(&winsock2_semaphore); |
192 | | LockSemaphoreInfo(winsock2_semaphore); |
193 | | } |
194 | | if (wsaData == (WSADATA *) NULL) |
195 | | { |
196 | | wsaData=(WSADATA *) AcquireMagickMemory(sizeof(WSADATA)); |
197 | | if (WSAStartup(MAKEWORD(2,2),wsaData) != 0) |
198 | | ThrowFatalException(CacheFatalError,"WSAStartup failed"); |
199 | | } |
200 | | if (use_lock != MagickFalse) |
201 | | UnlockSemaphoreInfo(winsock2_semaphore); |
202 | | } |
203 | | #endif |
204 | | |
205 | | #if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) |
206 | | static int ConnectPixelCacheServer(const char *magick_unused(hostname), |
207 | | const int magick_unused(port),size_t *magick_unused(session_key), |
208 | | ExceptionInfo *exception) |
209 | | { |
210 | | magick_unreferenced(hostname); |
211 | | magick_unreferenced(port); |
212 | | magick_unreferenced(session_key); |
213 | | (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError, |
214 | | "DelegateLibrarySupportNotBuiltIn","distributed pixel cache"); |
215 | | return(MagickFalse); |
216 | | } |
217 | | #else |
218 | | static int ConnectPixelCacheServer(const char *hostname,const int port, |
219 | | size_t *session_key,ExceptionInfo *exception) |
220 | 0 | { |
221 | 0 | char |
222 | 0 | service[MagickPathExtent], |
223 | 0 | *shared_secret; |
224 | |
|
225 | 0 | int |
226 | 0 | status; |
227 | |
|
228 | 0 | SOCKET_TYPE |
229 | 0 | client_socket; |
230 | |
|
231 | 0 | StringInfo |
232 | 0 | *nonce; |
233 | |
|
234 | 0 | ssize_t |
235 | 0 | count; |
236 | |
|
237 | 0 | struct addrinfo |
238 | 0 | hint, |
239 | 0 | *result; |
240 | | |
241 | | /* |
242 | | Connect to distributed pixel cache and get session key. |
243 | | */ |
244 | 0 | *session_key=0; |
245 | | #if defined(MAGICKCORE_HAVE_WINSOCK2) |
246 | | InitializeWinsock2(MagickTrue); |
247 | | #endif |
248 | 0 | (void) memset(&hint,0,sizeof(hint)); |
249 | 0 | hint.ai_family=AF_INET; |
250 | 0 | hint.ai_socktype=SOCK_STREAM; |
251 | 0 | hint.ai_flags=AI_PASSIVE; |
252 | 0 | (void) FormatLocaleString(service,MagickPathExtent,"%d",port); |
253 | 0 | status=getaddrinfo(hostname,service,&hint,&result); |
254 | 0 | if (status != 0) |
255 | 0 | { |
256 | 0 | (void) ThrowMagickException(exception,GetMagickModule(),CacheError, |
257 | 0 | "DistributedPixelCache","'%s': %s",hostname,GetExceptionMessage(errno)); |
258 | 0 | return(-1); |
259 | 0 | } |
260 | 0 | client_socket=socket(result->ai_family,result->ai_socktype, |
261 | 0 | result->ai_protocol); |
262 | 0 | if (client_socket == -1) |
263 | 0 | { |
264 | 0 | freeaddrinfo(result); |
265 | 0 | (void) ThrowMagickException(exception,GetMagickModule(),CacheError, |
266 | 0 | "DistributedPixelCache","'%s': %s",hostname,GetExceptionMessage(errno)); |
267 | 0 | return(-1); |
268 | 0 | } |
269 | 0 | status=connect(client_socket,result->ai_addr,(socklen_t) result->ai_addrlen); |
270 | 0 | freeaddrinfo(result); |
271 | 0 | if (status == -1) |
272 | 0 | { |
273 | 0 | CLOSE_SOCKET(client_socket); |
274 | 0 | (void) ThrowMagickException(exception,GetMagickModule(),CacheError, |
275 | 0 | "DistributedPixelCache","'%s': %s",hostname,GetExceptionMessage(errno)); |
276 | 0 | return(-1); |
277 | 0 | } |
278 | 0 | count=recv(client_socket,(char *) session_key,sizeof(*session_key),0); |
279 | 0 | if (count == -1) |
280 | 0 | { |
281 | 0 | CLOSE_SOCKET(client_socket); |
282 | 0 | (void) ThrowMagickException(exception,GetMagickModule(),CacheError, |
283 | 0 | "DistributedPixelCache","'%s': %s",hostname,GetExceptionMessage(errno)); |
284 | 0 | return(-1); |
285 | 0 | } |
286 | | /* |
287 | | Authenticate client session key to server session key. |
288 | | */ |
289 | 0 | shared_secret=GetPolicyValue("cache:shared-secret"); |
290 | 0 | if (shared_secret == (char *) NULL) |
291 | 0 | { |
292 | 0 | CLOSE_SOCKET(client_socket); |
293 | 0 | (void) ThrowMagickException(exception,GetMagickModule(),CacheError, |
294 | 0 | "DistributedPixelCache","'%s': shared secret required",hostname); |
295 | 0 | return(-1); |
296 | 0 | } |
297 | 0 | nonce=StringToStringInfo(shared_secret); |
298 | 0 | if ((size_t) GetMagickSignature(nonce) != *session_key) |
299 | 0 | { |
300 | 0 | CLOSE_SOCKET(client_socket); |
301 | 0 | (void) ThrowMagickException(exception,GetMagickModule(),CacheError, |
302 | 0 | "DistributedPixelCache","'%s' authentication failed",hostname); |
303 | 0 | return(-1); |
304 | 0 | } |
305 | 0 | shared_secret=DestroyString(shared_secret); |
306 | 0 | nonce=DestroyStringInfo(nonce); |
307 | 0 | return((int) client_socket); |
308 | 0 | } |
309 | | #endif |
310 | | |
311 | | static char *GetHostname(int *port,ExceptionInfo *exception) |
312 | 0 | { |
313 | 0 | char |
314 | 0 | *host, |
315 | 0 | *hosts, |
316 | 0 | **hostlist; |
317 | |
|
318 | 0 | int |
319 | 0 | argc; |
320 | |
|
321 | 0 | ssize_t |
322 | 0 | i; |
323 | |
|
324 | 0 | static size_t |
325 | 0 | id = 0; |
326 | | |
327 | | /* |
328 | | Parse host list (e.g. 192.168.100.1:6668,192.168.100.2:6668). |
329 | | */ |
330 | 0 | hosts=(char *) GetImageRegistry(StringRegistryType,"cache:hosts",exception); |
331 | 0 | if (hosts == (char *) NULL) |
332 | 0 | { |
333 | 0 | *port=DPCPort; |
334 | 0 | return(AcquireString(DPCHostname)); |
335 | 0 | } |
336 | 0 | (void) SubstituteString(&hosts,","," "); |
337 | 0 | hostlist=StringToArgv(hosts,&argc); |
338 | 0 | hosts=DestroyString(hosts); |
339 | 0 | if (hostlist == (char **) NULL) |
340 | 0 | { |
341 | 0 | *port=DPCPort; |
342 | 0 | return(AcquireString(DPCHostname)); |
343 | 0 | } |
344 | 0 | hosts=AcquireString(hostlist[(id++ % ((size_t) argc-1))+1]); |
345 | 0 | for (i=0; i < (ssize_t) argc; i++) |
346 | 0 | hostlist[i]=DestroyString(hostlist[i]); |
347 | 0 | hostlist=(char **) RelinquishMagickMemory(hostlist); |
348 | 0 | (void) SubstituteString(&hosts,":"," "); |
349 | 0 | hostlist=StringToArgv(hosts,&argc); |
350 | 0 | if (hostlist == (char **) NULL) |
351 | 0 | { |
352 | 0 | *port=DPCPort; |
353 | 0 | return(AcquireString(DPCHostname)); |
354 | 0 | } |
355 | 0 | host=AcquireString(hostlist[1]); |
356 | 0 | if (hostlist[2] == (char *) NULL) |
357 | 0 | *port=DPCPort; |
358 | 0 | else |
359 | 0 | *port=StringToLong(hostlist[2]); |
360 | 0 | for (i=0; i < (ssize_t) argc; i++) |
361 | 0 | hostlist[i]=DestroyString(hostlist[i]); |
362 | 0 | hostlist=(char **) RelinquishMagickMemory(hostlist); |
363 | 0 | return(host); |
364 | 0 | } |
365 | | |
366 | | MagickPrivate DistributeCacheInfo *AcquireDistributeCacheInfo( |
367 | | ExceptionInfo *exception) |
368 | 0 | { |
369 | 0 | char |
370 | 0 | *hostname; |
371 | |
|
372 | 0 | DistributeCacheInfo |
373 | 0 | *server_info; |
374 | |
|
375 | 0 | size_t |
376 | 0 | session_key; |
377 | | |
378 | | /* |
379 | | Connect to the distributed pixel cache server. |
380 | | */ |
381 | 0 | server_info=(DistributeCacheInfo *) AcquireCriticalMemory( |
382 | 0 | sizeof(*server_info)); |
383 | 0 | (void) memset(server_info,0,sizeof(*server_info)); |
384 | 0 | server_info->signature=MagickCoreSignature; |
385 | 0 | server_info->port=0; |
386 | 0 | hostname=GetHostname(&server_info->port,exception); |
387 | 0 | session_key=0; |
388 | 0 | server_info->file=ConnectPixelCacheServer(hostname,server_info->port, |
389 | 0 | &session_key,exception); |
390 | 0 | if (server_info->file == -1) |
391 | 0 | server_info=DestroyDistributeCacheInfo(server_info); |
392 | 0 | else |
393 | 0 | { |
394 | 0 | server_info->session_key=session_key; |
395 | 0 | (void) CopyMagickString(server_info->hostname,hostname,MagickPathExtent); |
396 | 0 | server_info->debug=(GetLogEventMask() & CacheEvent) != 0 ? MagickTrue : |
397 | 0 | MagickFalse; |
398 | 0 | } |
399 | 0 | hostname=DestroyString(hostname); |
400 | 0 | return(server_info); |
401 | 0 | } |
402 | | |
403 | | /* |
404 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
405 | | % % |
406 | | % % |
407 | | % % |
408 | | + D e s t r o y D i s t r i b u t e C a c h e I n f o % |
409 | | % % |
410 | | % % |
411 | | % % |
412 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
413 | | % |
414 | | % DestroyDistributeCacheInfo() deallocates memory associated with an |
415 | | % DistributeCacheInfo structure. |
416 | | % |
417 | | % The format of the DestroyDistributeCacheInfo method is: |
418 | | % |
419 | | % DistributeCacheInfo *DestroyDistributeCacheInfo( |
420 | | % DistributeCacheInfo *server_info) |
421 | | % |
422 | | % A description of each parameter follows: |
423 | | % |
424 | | % o server_info: the distributed cache info. |
425 | | % |
426 | | */ |
427 | | MagickPrivate DistributeCacheInfo *DestroyDistributeCacheInfo( |
428 | | DistributeCacheInfo *server_info) |
429 | 0 | { |
430 | 0 | assert(server_info != (DistributeCacheInfo *) NULL); |
431 | 0 | assert(server_info->signature == MagickCoreSignature); |
432 | 0 | #if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) |
433 | 0 | if (server_info->file > 0) |
434 | 0 | CLOSE_SOCKET(server_info->file); |
435 | 0 | #endif |
436 | 0 | server_info->signature=(~MagickCoreSignature); |
437 | 0 | server_info=(DistributeCacheInfo *) RelinquishMagickMemory(server_info); |
438 | 0 | return(server_info); |
439 | 0 | } |
440 | | |
441 | | /* |
442 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
443 | | % % |
444 | | % % |
445 | | % % |
446 | | + D i s t r i b u t e P i x e l C a c h e S e r v e r % |
447 | | % % |
448 | | % % |
449 | | % % |
450 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
451 | | % |
452 | | % DistributePixelCacheServer() waits on the specified port for commands to |
453 | | % create, read, update, or destroy a pixel cache. |
454 | | % |
455 | | % The format of the DistributePixelCacheServer() method is: |
456 | | % |
457 | | % void DistributePixelCacheServer(const int port) |
458 | | % |
459 | | % A description of each parameter follows: |
460 | | % |
461 | | % o port: connect the distributed pixel cache at this port. |
462 | | % |
463 | | % o exception: return any errors or warnings in this structure. |
464 | | % |
465 | | */ |
466 | | |
467 | | #if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) |
468 | | static inline MagickOffsetType dpc_send(SOCKET_TYPE magick_unused(file), |
469 | | const MagickSizeType magick_unused(length), |
470 | | const void *magick_restrict magick_unused(message)) |
471 | | { |
472 | | magick_unreferenced(file); |
473 | | magick_unreferenced(length); |
474 | | magick_unreferenced(message); |
475 | | return(-1); |
476 | | } |
477 | | #else |
478 | | static inline MagickOffsetType dpc_send(SOCKET_TYPE file,const MagickSizeType length, |
479 | | const void *magick_restrict message) |
480 | 0 | { |
481 | 0 | MagickOffsetType |
482 | 0 | i; |
483 | |
|
484 | 0 | ssize_t |
485 | 0 | count; |
486 | | |
487 | | /* |
488 | | Ensure a complete message is sent. |
489 | | */ |
490 | 0 | count=0; |
491 | 0 | for (i=0; i < (MagickOffsetType) length; i+=count) |
492 | 0 | { |
493 | 0 | count=(ssize_t) send(file,(char *) message+i,(LENGTH_TYPE) |
494 | 0 | MagickMin(length-(MagickSizeType) i,(MagickSizeType) MagickMaxBufferExtent), |
495 | 0 | MSG_NOSIGNAL); |
496 | 0 | if (count <= 0) |
497 | 0 | { |
498 | 0 | count=0; |
499 | 0 | if (errno != EINTR) |
500 | 0 | break; |
501 | 0 | } |
502 | 0 | } |
503 | 0 | return(i); |
504 | 0 | } |
505 | | #endif |
506 | | |
507 | | #if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) |
508 | | MagickExport void DistributePixelCacheServer(const int magick_unused(port), |
509 | | ExceptionInfo *magick_unused(exception)) |
510 | | { |
511 | | magick_unreferenced(port); |
512 | | magick_unreferenced(exception); |
513 | | ThrowFatalException(MissingDelegateError,"DelegateLibrarySupportNotBuiltIn"); |
514 | | } |
515 | | #else |
516 | | static MagickBooleanType DestroyDistributeCache(SplayTreeInfo *registry, |
517 | | const size_t session_key) |
518 | 0 | { |
519 | 0 | MagickAddressType |
520 | 0 | key = (MagickAddressType) session_key; |
521 | | |
522 | | /* |
523 | | Destroy distributed pixel cache. |
524 | | */ |
525 | 0 | return(DeleteNodeFromSplayTree(registry,(const void *) key)); |
526 | 0 | } |
527 | | |
528 | | static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry, |
529 | | SOCKET_TYPE file,const size_t session_key,ExceptionInfo *exception) |
530 | 0 | { |
531 | 0 | Image |
532 | 0 | *image; |
533 | |
|
534 | 0 | MagickAddressType |
535 | 0 | key = (MagickAddressType) session_key; |
536 | |
|
537 | 0 | MagickBooleanType |
538 | 0 | status; |
539 | |
|
540 | 0 | MagickOffsetType |
541 | 0 | count; |
542 | |
|
543 | 0 | MagickSizeType |
544 | 0 | length; |
545 | |
|
546 | 0 | unsigned char |
547 | 0 | message[MagickPathExtent], |
548 | 0 | *p; |
549 | | |
550 | | /* |
551 | | Open distributed pixel cache. |
552 | | */ |
553 | 0 | image=AcquireImage((ImageInfo *) NULL,exception); |
554 | 0 | if (image == (Image *) NULL) |
555 | 0 | return(MagickFalse); |
556 | 0 | length=sizeof(image->storage_class)+sizeof(image->colorspace)+ |
557 | 0 | sizeof(image->alpha_trait)+sizeof(image->channels)+sizeof(image->columns)+ |
558 | 0 | sizeof(image->rows)+sizeof(image->number_channels)+MaxPixelChannels* |
559 | 0 | sizeof(*image->channel_map)+sizeof(image->metacontent_extent); |
560 | 0 | count=dpc_read(file,length,message); |
561 | 0 | if (count != (MagickOffsetType) length) |
562 | 0 | return(MagickFalse); |
563 | | /* |
564 | | Deserialize the image attributes. |
565 | | */ |
566 | 0 | p=message; |
567 | 0 | (void) memcpy(&image->storage_class,p,sizeof(image->storage_class)); |
568 | 0 | p+=(ptrdiff_t) sizeof(image->storage_class); |
569 | 0 | (void) memcpy(&image->colorspace,p,sizeof(image->colorspace)); |
570 | 0 | p+=(ptrdiff_t) sizeof(image->colorspace); |
571 | 0 | (void) memcpy(&image->alpha_trait,p,sizeof(image->alpha_trait)); |
572 | 0 | p+=(ptrdiff_t) sizeof(image->alpha_trait); |
573 | 0 | (void) memcpy(&image->channels,p,sizeof(image->channels)); |
574 | 0 | p+=(ptrdiff_t) sizeof(image->channels); |
575 | 0 | (void) memcpy(&image->columns,p,sizeof(image->columns)); |
576 | 0 | p+=(ptrdiff_t) sizeof(image->columns); |
577 | 0 | (void) memcpy(&image->rows,p,sizeof(image->rows)); |
578 | 0 | p+=(ptrdiff_t) sizeof(image->rows); |
579 | 0 | (void) memcpy(&image->number_channels,p,sizeof(image->number_channels)); |
580 | 0 | p+=(ptrdiff_t) sizeof(image->number_channels); |
581 | 0 | (void) memcpy(image->channel_map,p,MaxPixelChannels* |
582 | 0 | sizeof(*image->channel_map)); |
583 | 0 | p+=(ptrdiff_t) MaxPixelChannels*sizeof(*image->channel_map); |
584 | 0 | (void) memcpy(&image->metacontent_extent,p,sizeof(image->metacontent_extent)); |
585 | 0 | p+=(ptrdiff_t) sizeof(image->metacontent_extent); |
586 | 0 | if (SyncImagePixelCache(image,exception) == MagickFalse) |
587 | 0 | return(MagickFalse); |
588 | 0 | status=AddValueToSplayTree(registry,(const void *) key,image); |
589 | 0 | return(status); |
590 | 0 | } |
591 | | |
592 | | static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry, |
593 | | SOCKET_TYPE file,const size_t session_key,ExceptionInfo *exception) |
594 | 0 | { |
595 | 0 | const Quantum |
596 | 0 | *p; |
597 | |
|
598 | 0 | const unsigned char |
599 | 0 | *metacontent; |
600 | |
|
601 | 0 | Image |
602 | 0 | *image; |
603 | |
|
604 | 0 | MagickAddressType |
605 | 0 | key = (MagickAddressType) session_key; |
606 | |
|
607 | 0 | MagickOffsetType |
608 | 0 | count; |
609 | |
|
610 | 0 | MagickSizeType |
611 | 0 | length; |
612 | |
|
613 | 0 | RectangleInfo |
614 | 0 | region; |
615 | |
|
616 | 0 | unsigned char |
617 | 0 | message[MagickPathExtent], |
618 | 0 | *q; |
619 | | |
620 | | /* |
621 | | Read distributed pixel cache metacontent. |
622 | | */ |
623 | 0 | image=(Image *) GetValueFromSplayTree(registry,(const void *) key); |
624 | 0 | if (image == (Image *) NULL) |
625 | 0 | return(MagickFalse); |
626 | 0 | length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ |
627 | 0 | sizeof(region.y)+sizeof(length); |
628 | 0 | count=dpc_read(file,length,message); |
629 | 0 | if (count != (MagickOffsetType) length) |
630 | 0 | return(MagickFalse); |
631 | 0 | q=message; |
632 | 0 | (void) memcpy(®ion.width,q,sizeof(region.width)); |
633 | 0 | q+=(ptrdiff_t) sizeof(region.width); |
634 | 0 | (void) memcpy(®ion.height,q,sizeof(region.height)); |
635 | 0 | q+=(ptrdiff_t) sizeof(region.height); |
636 | 0 | (void) memcpy(®ion.x,q,sizeof(region.x)); |
637 | 0 | q+=(ptrdiff_t) sizeof(region.x); |
638 | 0 | (void) memcpy(®ion.y,q,sizeof(region.y)); |
639 | 0 | q+=(ptrdiff_t) sizeof(region.y); |
640 | 0 | (void) memcpy(&length,q,sizeof(length)); |
641 | 0 | q+=(ptrdiff_t) sizeof(length); |
642 | 0 | p=GetVirtualPixels(image,region.x,region.y,region.width,region.height, |
643 | 0 | exception); |
644 | 0 | if (p == (const Quantum *) NULL) |
645 | 0 | return(MagickFalse); |
646 | 0 | metacontent=(const unsigned char *) GetVirtualMetacontent(image); |
647 | 0 | count=dpc_send(file,length,metacontent); |
648 | 0 | if (count != (MagickOffsetType) length) |
649 | 0 | return(MagickFalse); |
650 | 0 | return(MagickTrue); |
651 | 0 | } |
652 | | |
653 | | static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry, |
654 | | SOCKET_TYPE file,const size_t session_key,ExceptionInfo *exception) |
655 | 0 | { |
656 | 0 | const Quantum |
657 | 0 | *p; |
658 | |
|
659 | 0 | Image |
660 | 0 | *image; |
661 | |
|
662 | 0 | MagickAddressType |
663 | 0 | key = (MagickAddressType) session_key; |
664 | |
|
665 | 0 | MagickOffsetType |
666 | 0 | count; |
667 | |
|
668 | 0 | MagickSizeType |
669 | 0 | length; |
670 | |
|
671 | 0 | RectangleInfo |
672 | 0 | region; |
673 | |
|
674 | 0 | unsigned char |
675 | 0 | message[MagickPathExtent], |
676 | 0 | *q; |
677 | | |
678 | | /* |
679 | | Read distributed pixel cache pixels. |
680 | | */ |
681 | 0 | image=(Image *) GetValueFromSplayTree(registry,(const void *) key); |
682 | 0 | if (image == (Image *) NULL) |
683 | 0 | return(MagickFalse); |
684 | 0 | length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ |
685 | 0 | sizeof(region.y)+sizeof(length); |
686 | 0 | count=dpc_read(file,length,message); |
687 | 0 | if (count != (MagickOffsetType) length) |
688 | 0 | return(MagickFalse); |
689 | 0 | q=message; |
690 | 0 | (void) memcpy(®ion.width,q,sizeof(region.width)); |
691 | 0 | q+=(ptrdiff_t) sizeof(region.width); |
692 | 0 | (void) memcpy(®ion.height,q,sizeof(region.height)); |
693 | 0 | q+=(ptrdiff_t) sizeof(region.height); |
694 | 0 | (void) memcpy(®ion.x,q,sizeof(region.x)); |
695 | 0 | q+=(ptrdiff_t) sizeof(region.x); |
696 | 0 | (void) memcpy(®ion.y,q,sizeof(region.y)); |
697 | 0 | q+=(ptrdiff_t) sizeof(region.y); |
698 | 0 | (void) memcpy(&length,q,sizeof(length)); |
699 | 0 | q+=(ptrdiff_t) sizeof(length); |
700 | 0 | p=GetVirtualPixels(image,region.x,region.y,region.width,region.height, |
701 | 0 | exception); |
702 | 0 | if (p == (const Quantum *) NULL) |
703 | 0 | return(MagickFalse); |
704 | 0 | count=dpc_send(file,length,p); |
705 | 0 | if (count != (MagickOffsetType) length) |
706 | 0 | return(MagickFalse); |
707 | 0 | return(MagickTrue); |
708 | 0 | } |
709 | | |
710 | | static void *RelinquishImageRegistry(void *image) |
711 | 0 | { |
712 | 0 | return((void *) DestroyImageList((Image *) image)); |
713 | 0 | } |
714 | | |
715 | | static MagickBooleanType WriteDistributeCacheMetacontent( |
716 | | SplayTreeInfo *registry,SOCKET_TYPE file,const size_t session_key, |
717 | | ExceptionInfo *exception) |
718 | 0 | { |
719 | 0 | Image |
720 | 0 | *image; |
721 | |
|
722 | 0 | MagickAddressType |
723 | 0 | key = (MagickAddressType) session_key; |
724 | |
|
725 | 0 | MagickOffsetType |
726 | 0 | count; |
727 | |
|
728 | 0 | MagickSizeType |
729 | 0 | length; |
730 | |
|
731 | 0 | Quantum |
732 | 0 | *q; |
733 | |
|
734 | 0 | RectangleInfo |
735 | 0 | region; |
736 | |
|
737 | 0 | unsigned char |
738 | 0 | message[MagickPathExtent], |
739 | 0 | *metacontent, |
740 | 0 | *p; |
741 | | |
742 | | /* |
743 | | Write distributed pixel cache metacontent. |
744 | | */ |
745 | 0 | key=session_key; |
746 | 0 | image=(Image *) GetValueFromSplayTree(registry,(const void *) key); |
747 | 0 | if (image == (Image *) NULL) |
748 | 0 | return(MagickFalse); |
749 | 0 | length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ |
750 | 0 | sizeof(region.y)+sizeof(length); |
751 | 0 | count=dpc_read(file,length,message); |
752 | 0 | if (count != (MagickOffsetType) length) |
753 | 0 | return(MagickFalse); |
754 | 0 | p=message; |
755 | 0 | (void) memcpy(®ion.width,p,sizeof(region.width)); |
756 | 0 | p+=(ptrdiff_t) sizeof(region.width); |
757 | 0 | (void) memcpy(®ion.height,p,sizeof(region.height)); |
758 | 0 | p+=(ptrdiff_t) sizeof(region.height); |
759 | 0 | (void) memcpy(®ion.x,p,sizeof(region.x)); |
760 | 0 | p+=(ptrdiff_t) sizeof(region.x); |
761 | 0 | (void) memcpy(®ion.y,p,sizeof(region.y)); |
762 | 0 | p+=(ptrdiff_t) sizeof(region.y); |
763 | 0 | (void) memcpy(&length,p,sizeof(length)); |
764 | 0 | p+=(ptrdiff_t) sizeof(length); |
765 | 0 | q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height, |
766 | 0 | exception); |
767 | 0 | if (q == (Quantum *) NULL) |
768 | 0 | return(MagickFalse); |
769 | 0 | metacontent=(unsigned char *) GetAuthenticMetacontent(image); |
770 | 0 | count=dpc_read(file,length,metacontent); |
771 | 0 | if (count != (MagickOffsetType) length) |
772 | 0 | return(MagickFalse); |
773 | 0 | return(SyncAuthenticPixels(image,exception)); |
774 | 0 | } |
775 | | |
776 | | static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry, |
777 | | SOCKET_TYPE file,const size_t session_key,ExceptionInfo *exception) |
778 | 0 | { |
779 | 0 | Image |
780 | 0 | *image; |
781 | |
|
782 | 0 | MagickAddressType |
783 | 0 | key = (MagickAddressType) session_key; |
784 | |
|
785 | 0 | MagickOffsetType |
786 | 0 | count; |
787 | |
|
788 | 0 | MagickSizeType |
789 | 0 | length; |
790 | |
|
791 | 0 | Quantum |
792 | 0 | *q; |
793 | |
|
794 | 0 | RectangleInfo |
795 | 0 | region; |
796 | |
|
797 | 0 | unsigned char |
798 | 0 | message[MagickPathExtent], |
799 | 0 | *p; |
800 | | |
801 | | /* |
802 | | Write distributed pixel cache pixels. |
803 | | */ |
804 | 0 | image=(Image *) GetValueFromSplayTree(registry,(const void *) key); |
805 | 0 | if (image == (Image *) NULL) |
806 | 0 | return(MagickFalse); |
807 | 0 | length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ |
808 | 0 | sizeof(region.y)+sizeof(length); |
809 | 0 | count=dpc_read(file,length,message); |
810 | 0 | if (count != (MagickOffsetType) length) |
811 | 0 | return(MagickFalse); |
812 | 0 | p=message; |
813 | 0 | (void) memcpy(®ion.width,p,sizeof(region.width)); |
814 | 0 | p+=(ptrdiff_t) sizeof(region.width); |
815 | 0 | (void) memcpy(®ion.height,p,sizeof(region.height)); |
816 | 0 | p+=(ptrdiff_t) sizeof(region.height); |
817 | 0 | (void) memcpy(®ion.x,p,sizeof(region.x)); |
818 | 0 | p+=(ptrdiff_t) sizeof(region.x); |
819 | 0 | (void) memcpy(®ion.y,p,sizeof(region.y)); |
820 | 0 | p+=(ptrdiff_t) sizeof(region.y); |
821 | 0 | (void) memcpy(&length,p,sizeof(length)); |
822 | 0 | p+=(ptrdiff_t) sizeof(length); |
823 | 0 | q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height, |
824 | 0 | exception); |
825 | 0 | if (q == (Quantum *) NULL) |
826 | 0 | return(MagickFalse); |
827 | 0 | count=dpc_read(file,length,(unsigned char *) q); |
828 | 0 | if (count != (MagickOffsetType) length) |
829 | 0 | return(MagickFalse); |
830 | 0 | return(SyncAuthenticPixels(image,exception)); |
831 | 0 | } |
832 | | |
833 | | static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket) |
834 | 0 | { |
835 | 0 | char |
836 | 0 | *shared_secret; |
837 | |
|
838 | 0 | ExceptionInfo |
839 | 0 | *exception; |
840 | |
|
841 | 0 | MagickBooleanType |
842 | 0 | status = MagickFalse; |
843 | |
|
844 | 0 | MagickOffsetType |
845 | 0 | count; |
846 | |
|
847 | 0 | size_t |
848 | 0 | key, |
849 | 0 | session_key; |
850 | |
|
851 | 0 | SOCKET_TYPE |
852 | 0 | client_socket; |
853 | |
|
854 | 0 | SplayTreeInfo |
855 | 0 | *registry; |
856 | |
|
857 | 0 | StringInfo |
858 | 0 | *nonce; |
859 | |
|
860 | 0 | unsigned char |
861 | 0 | command; |
862 | | |
863 | | /* |
864 | | Generate session key. |
865 | | */ |
866 | 0 | shared_secret=GetPolicyValue("cache:shared-secret"); |
867 | 0 | if (shared_secret == (char *) NULL) |
868 | 0 | ThrowFatalException(CacheFatalError,"shared secret required"); |
869 | 0 | nonce=StringToStringInfo(shared_secret); |
870 | 0 | shared_secret=DestroyString(shared_secret); |
871 | 0 | session_key=GetMagickSignature(nonce); |
872 | 0 | nonce=DestroyStringInfo(nonce); |
873 | 0 | exception=AcquireExceptionInfo(); |
874 | | /* |
875 | | Process client commands. |
876 | | */ |
877 | 0 | registry=NewSplayTree((int (*)(const void *,const void *)) NULL, |
878 | 0 | (void *(*)(void *)) NULL,RelinquishImageRegistry); |
879 | 0 | client_socket=(*(SOCKET_TYPE *) socket); |
880 | 0 | count=dpc_send(client_socket,sizeof(session_key),&session_key); |
881 | 0 | for (status=MagickFalse; ; ) |
882 | 0 | { |
883 | 0 | count=dpc_read(client_socket,1,(unsigned char *) &command); |
884 | 0 | if (count <= 0) |
885 | 0 | break; |
886 | 0 | count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key); |
887 | 0 | if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key)) |
888 | 0 | break; |
889 | 0 | switch (command) |
890 | 0 | { |
891 | 0 | case 'o': |
892 | 0 | { |
893 | 0 | status=OpenDistributeCache(registry,client_socket,session_key, |
894 | 0 | exception); |
895 | 0 | count=dpc_send(client_socket,sizeof(status),&status); |
896 | 0 | break; |
897 | 0 | } |
898 | 0 | case 'r': |
899 | 0 | { |
900 | 0 | status=ReadDistributeCachePixels(registry,client_socket,session_key, |
901 | 0 | exception); |
902 | 0 | break; |
903 | 0 | } |
904 | 0 | case 'R': |
905 | 0 | { |
906 | 0 | status=ReadDistributeCacheMetacontent(registry,client_socket, |
907 | 0 | session_key,exception); |
908 | 0 | break; |
909 | 0 | } |
910 | 0 | case 'w': |
911 | 0 | { |
912 | 0 | status=WriteDistributeCachePixels(registry,client_socket,session_key, |
913 | 0 | exception); |
914 | 0 | break; |
915 | 0 | } |
916 | 0 | case 'W': |
917 | 0 | { |
918 | 0 | status=WriteDistributeCacheMetacontent(registry,client_socket, |
919 | 0 | session_key,exception); |
920 | 0 | break; |
921 | 0 | } |
922 | 0 | case 'd': |
923 | 0 | { |
924 | 0 | status=DestroyDistributeCache(registry,session_key); |
925 | 0 | break; |
926 | 0 | } |
927 | 0 | default: |
928 | 0 | break; |
929 | 0 | } |
930 | 0 | if (status == MagickFalse) |
931 | 0 | break; |
932 | 0 | if (command == 'd') |
933 | 0 | break; |
934 | 0 | } |
935 | 0 | count=dpc_send(client_socket,sizeof(status),&status); |
936 | 0 | CLOSE_SOCKET(client_socket); |
937 | 0 | exception=DestroyExceptionInfo(exception); |
938 | 0 | registry=DestroySplayTree(registry); |
939 | 0 | return(HANDLER_RETURN_VALUE); |
940 | 0 | } |
941 | | |
942 | | MagickExport void DistributePixelCacheServer(const int port, |
943 | | ExceptionInfo *exception) |
944 | 0 | { |
945 | 0 | char |
946 | 0 | service[MagickPathExtent]; |
947 | |
|
948 | 0 | int |
949 | 0 | status; |
950 | |
|
951 | 0 | #if defined(MAGICKCORE_THREAD_SUPPORT) |
952 | 0 | pthread_attr_t |
953 | 0 | attributes; |
954 | |
|
955 | 0 | pthread_t |
956 | 0 | threads; |
957 | | #elif defined(_MSC_VER) |
958 | | DWORD |
959 | | threadID; |
960 | | #else |
961 | | Not implemented! |
962 | | #endif |
963 | |
|
964 | 0 | struct addrinfo |
965 | 0 | *p; |
966 | |
|
967 | 0 | SOCKET_TYPE |
968 | 0 | server_socket; |
969 | |
|
970 | 0 | struct addrinfo |
971 | 0 | hint, |
972 | 0 | *result; |
973 | |
|
974 | 0 | struct sockaddr_in |
975 | 0 | address; |
976 | | |
977 | | /* |
978 | | Launch distributed pixel cache server. |
979 | | */ |
980 | 0 | assert(exception != (ExceptionInfo *) NULL); |
981 | 0 | assert(exception->signature == MagickCoreSignature); |
982 | 0 | magick_unreferenced(exception); |
983 | | #if defined(MAGICKCORE_HAVE_WINSOCK2) |
984 | | InitializeWinsock2(MagickFalse); |
985 | | #endif |
986 | 0 | (void) memset(&hint,0,sizeof(hint)); |
987 | 0 | hint.ai_family=AF_INET; |
988 | 0 | hint.ai_socktype=SOCK_STREAM; |
989 | 0 | hint.ai_flags=AI_PASSIVE; |
990 | 0 | (void) FormatLocaleString(service,MagickPathExtent,"%d",port); |
991 | 0 | status=getaddrinfo((const char *) NULL,service,&hint,&result); |
992 | 0 | if (status != 0) |
993 | 0 | ThrowFatalException(CacheFatalError,"UnableToListen"); |
994 | 0 | server_socket=(SOCKET_TYPE) 0; |
995 | 0 | for (p=result; p != (struct addrinfo *) NULL; p=p->ai_next) |
996 | 0 | { |
997 | 0 | int |
998 | 0 | one; |
999 | |
|
1000 | 0 | server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol); |
1001 | 0 | if (server_socket == -1) |
1002 | 0 | continue; |
1003 | 0 | one=1; |
1004 | 0 | status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,(char *) &one, |
1005 | 0 | (socklen_t) sizeof(one)); |
1006 | 0 | if (status == -1) |
1007 | 0 | { |
1008 | 0 | CLOSE_SOCKET(server_socket); |
1009 | 0 | continue; |
1010 | 0 | } |
1011 | 0 | status=bind(server_socket,p->ai_addr,(socklen_t) p->ai_addrlen); |
1012 | 0 | if (status == -1) |
1013 | 0 | { |
1014 | 0 | CLOSE_SOCKET(server_socket); |
1015 | 0 | continue; |
1016 | 0 | } |
1017 | 0 | break; |
1018 | 0 | } |
1019 | 0 | if (p == (struct addrinfo *) NULL) |
1020 | 0 | ThrowFatalException(CacheFatalError,"UnableToBind"); |
1021 | 0 | freeaddrinfo(result); |
1022 | 0 | status=listen(server_socket,DPCPendingConnections); |
1023 | 0 | if (status != 0) |
1024 | 0 | ThrowFatalException(CacheFatalError,"UnableToListen"); |
1025 | 0 | #if defined(MAGICKCORE_THREAD_SUPPORT) |
1026 | 0 | pthread_attr_init(&attributes); |
1027 | 0 | #endif |
1028 | 0 | for ( ; ; ) |
1029 | 0 | { |
1030 | 0 | SOCKET_TYPE |
1031 | 0 | client_socket; |
1032 | |
|
1033 | 0 | socklen_t |
1034 | 0 | length; |
1035 | |
|
1036 | 0 | length=(socklen_t) sizeof(address); |
1037 | 0 | client_socket=accept(server_socket,(struct sockaddr *) &address,&length); |
1038 | 0 | if (client_socket == -1) |
1039 | 0 | ThrowFatalException(CacheFatalError,"UnableToEstablishConnection"); |
1040 | 0 | #if defined(MAGICKCORE_THREAD_SUPPORT) |
1041 | 0 | status=pthread_create(&threads,&attributes,DistributePixelCacheClient, |
1042 | 0 | (void *) &client_socket); |
1043 | 0 | if (status == -1) |
1044 | 0 | ThrowFatalException(CacheFatalError,"UnableToCreateClientThread"); |
1045 | | #elif defined(_MSC_VER) |
1046 | | if (CreateThread(0,0,DistributePixelCacheClient,(void*) &client_socket,0,&threadID) == (HANDLE) NULL) |
1047 | | ThrowFatalException(CacheFatalError,"UnableToCreateClientThread"); |
1048 | | #else |
1049 | | Not implemented! |
1050 | | #endif |
1051 | 0 | } |
1052 | 0 | } |
1053 | | #endif |
1054 | | |
1055 | | /* |
1056 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1057 | | % % |
1058 | | % % |
1059 | | % % |
1060 | | + D i s t r i b u t e C a c h e T e r m i n u s % |
1061 | | % % |
1062 | | % % |
1063 | | % % |
1064 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1065 | | % |
1066 | | % DistributeCacheTerminus() destroys the Distributed Cache. |
1067 | | % |
1068 | | */ |
1069 | | MagickPrivate void DistributeCacheTerminus(void) |
1070 | 0 | { |
1071 | | #ifdef MAGICKCORE_HAVE_WINSOCK2 |
1072 | | if (winsock2_semaphore == (SemaphoreInfo *) NULL) |
1073 | | ActivateSemaphoreInfo(&winsock2_semaphore); |
1074 | | LockSemaphoreInfo(winsock2_semaphore); |
1075 | | if (wsaData != (WSADATA *) NULL) |
1076 | | { |
1077 | | WSACleanup(); |
1078 | | wsaData=(WSADATA *) RelinquishMagickMemory((void *) wsaData); |
1079 | | } |
1080 | | UnlockSemaphoreInfo(winsock2_semaphore); |
1081 | | RelinquishSemaphoreInfo(&winsock2_semaphore); |
1082 | | #endif |
1083 | 0 | } |
1084 | | |
1085 | | /* |
1086 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1087 | | % % |
1088 | | % % |
1089 | | % % |
1090 | | + G e t D i s t r i b u t e C a c h e F i l e % |
1091 | | % % |
1092 | | % % |
1093 | | % % |
1094 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1095 | | % |
1096 | | % GetDistributeCacheFile() returns the file associated with this |
1097 | | % DistributeCacheInfo structure. |
1098 | | % |
1099 | | % The format of the GetDistributeCacheFile method is: |
1100 | | % |
1101 | | % int GetDistributeCacheFile(const DistributeCacheInfo *server_info) |
1102 | | % |
1103 | | % A description of each parameter follows: |
1104 | | % |
1105 | | % o server_info: the distributed cache info. |
1106 | | % |
1107 | | */ |
1108 | | MagickPrivate int GetDistributeCacheFile(const DistributeCacheInfo *server_info) |
1109 | 0 | { |
1110 | 0 | assert(server_info != (DistributeCacheInfo *) NULL); |
1111 | 0 | assert(server_info->signature == MagickCoreSignature); |
1112 | 0 | return(server_info->file); |
1113 | 0 | } |
1114 | | |
1115 | | /* |
1116 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1117 | | % % |
1118 | | % % |
1119 | | % % |
1120 | | + G e t D i s t r i b u t e C a c h e H o s t n a m e % |
1121 | | % % |
1122 | | % % |
1123 | | % % |
1124 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1125 | | % |
1126 | | % GetDistributeCacheHostname() returns the hostname associated with this |
1127 | | % DistributeCacheInfo structure. |
1128 | | % |
1129 | | % The format of the GetDistributeCacheHostname method is: |
1130 | | % |
1131 | | % const char *GetDistributeCacheHostname( |
1132 | | % const DistributeCacheInfo *server_info) |
1133 | | % |
1134 | | % A description of each parameter follows: |
1135 | | % |
1136 | | % o server_info: the distributed cache info. |
1137 | | % |
1138 | | */ |
1139 | | MagickPrivate const char *GetDistributeCacheHostname( |
1140 | | const DistributeCacheInfo *server_info) |
1141 | 0 | { |
1142 | 0 | assert(server_info != (DistributeCacheInfo *) NULL); |
1143 | 0 | assert(server_info->signature == MagickCoreSignature); |
1144 | 0 | return(server_info->hostname); |
1145 | 0 | } |
1146 | | |
1147 | | /* |
1148 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1149 | | % % |
1150 | | % % |
1151 | | % % |
1152 | | + G e t D i s t r i b u t e C a c h e P o r t % |
1153 | | % % |
1154 | | % % |
1155 | | % % |
1156 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1157 | | % |
1158 | | % GetDistributeCachePort() returns the port associated with this |
1159 | | % DistributeCacheInfo structure. |
1160 | | % |
1161 | | % The format of the GetDistributeCachePort method is: |
1162 | | % |
1163 | | % int GetDistributeCachePort(const DistributeCacheInfo *server_info) |
1164 | | % |
1165 | | % A description of each parameter follows: |
1166 | | % |
1167 | | % o server_info: the distributed cache info. |
1168 | | % |
1169 | | */ |
1170 | | MagickPrivate int GetDistributeCachePort(const DistributeCacheInfo *server_info) |
1171 | 0 | { |
1172 | 0 | assert(server_info != (DistributeCacheInfo *) NULL); |
1173 | 0 | assert(server_info->signature == MagickCoreSignature); |
1174 | 0 | return(server_info->port); |
1175 | 0 | } |
1176 | | |
1177 | | /* |
1178 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1179 | | % % |
1180 | | % % |
1181 | | % % |
1182 | | + O p e n D i s t r i b u t e P i x e l C a c h e % |
1183 | | % % |
1184 | | % % |
1185 | | % % |
1186 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1187 | | % |
1188 | | % OpenDistributePixelCache() opens a pixel cache on a remote server. |
1189 | | % |
1190 | | % The format of the OpenDistributePixelCache method is: |
1191 | | % |
1192 | | % MagickBooleanType *OpenDistributePixelCache( |
1193 | | % DistributeCacheInfo *server_info,Image *image) |
1194 | | % |
1195 | | % A description of each parameter follows: |
1196 | | % |
1197 | | % o server_info: the distributed cache info. |
1198 | | % |
1199 | | % o image: the image. |
1200 | | % |
1201 | | */ |
1202 | | MagickPrivate MagickBooleanType OpenDistributePixelCache( |
1203 | | DistributeCacheInfo *server_info,Image *image) |
1204 | 0 | { |
1205 | 0 | MagickBooleanType |
1206 | 0 | status; |
1207 | |
|
1208 | 0 | MagickOffsetType |
1209 | 0 | count; |
1210 | |
|
1211 | 0 | unsigned char |
1212 | 0 | message[MagickPathExtent], |
1213 | 0 | *p; |
1214 | | |
1215 | | /* |
1216 | | Open distributed pixel cache. |
1217 | | */ |
1218 | 0 | assert(server_info != (DistributeCacheInfo *) NULL); |
1219 | 0 | assert(server_info->signature == MagickCoreSignature); |
1220 | 0 | assert(image != (Image *) NULL); |
1221 | 0 | assert(image->signature == MagickCoreSignature); |
1222 | 0 | p=message; |
1223 | 0 | *p++='o'; /* open */ |
1224 | | /* |
1225 | | Serialize image attributes (see ValidatePixelCacheMorphology()). |
1226 | | */ |
1227 | 0 | (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); |
1228 | 0 | p+=(ptrdiff_t) sizeof(server_info->session_key); |
1229 | 0 | (void) memcpy(p,&image->storage_class,sizeof(image->storage_class)); |
1230 | 0 | p+=(ptrdiff_t) sizeof(image->storage_class); |
1231 | 0 | (void) memcpy(p,&image->colorspace,sizeof(image->colorspace)); |
1232 | 0 | p+=(ptrdiff_t) sizeof(image->colorspace); |
1233 | 0 | (void) memcpy(p,&image->alpha_trait,sizeof(image->alpha_trait)); |
1234 | 0 | p+=(ptrdiff_t) sizeof(image->alpha_trait); |
1235 | 0 | (void) memcpy(p,&image->channels,sizeof(image->channels)); |
1236 | 0 | p+=(ptrdiff_t) sizeof(image->channels); |
1237 | 0 | (void) memcpy(p,&image->columns,sizeof(image->columns)); |
1238 | 0 | p+=(ptrdiff_t) sizeof(image->columns); |
1239 | 0 | (void) memcpy(p,&image->rows,sizeof(image->rows)); |
1240 | 0 | p+=(ptrdiff_t) sizeof(image->rows); |
1241 | 0 | (void) memcpy(p,&image->number_channels,sizeof(image->number_channels)); |
1242 | 0 | p+=(ptrdiff_t) sizeof(image->number_channels); |
1243 | 0 | (void) memcpy(p,image->channel_map,MaxPixelChannels* |
1244 | 0 | sizeof(*image->channel_map)); |
1245 | 0 | p+=(ptrdiff_t) MaxPixelChannels*sizeof(*image->channel_map); |
1246 | 0 | (void) memcpy(p,&image->metacontent_extent,sizeof(image->metacontent_extent)); |
1247 | 0 | p+=(ptrdiff_t) sizeof(image->metacontent_extent); |
1248 | 0 | count=dpc_send(server_info->file,(MagickSizeType) (p-message),message); |
1249 | 0 | if (count != (MagickOffsetType) (p-message)) |
1250 | 0 | return(MagickFalse); |
1251 | 0 | status=MagickFalse; |
1252 | 0 | count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status); |
1253 | 0 | if (count != (MagickOffsetType) sizeof(status)) |
1254 | 0 | return(MagickFalse); |
1255 | 0 | return(status); |
1256 | 0 | } |
1257 | | |
1258 | | /* |
1259 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1260 | | % % |
1261 | | % % |
1262 | | % % |
1263 | | + R e a d D i s t r i b u t e P i x e l C a c h e M e t a c o n t e n t % |
1264 | | % % |
1265 | | % % |
1266 | | % % |
1267 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1268 | | % |
1269 | | % ReadDistributePixelCacheMetacontents() reads metacontent from the specified |
1270 | | % region of the distributed pixel cache. |
1271 | | % |
1272 | | % The format of the ReadDistributePixelCacheMetacontents method is: |
1273 | | % |
1274 | | % MagickOffsetType ReadDistributePixelCacheMetacontents( |
1275 | | % DistributeCacheInfo *server_info,const RectangleInfo *region, |
1276 | | % const MagickSizeType length,unsigned char *metacontent) |
1277 | | % |
1278 | | % A description of each parameter follows: |
1279 | | % |
1280 | | % o server_info: the distributed cache info. |
1281 | | % |
1282 | | % o image: the image. |
1283 | | % |
1284 | | % o region: read the metacontent from this region of the image. |
1285 | | % |
1286 | | % o length: the length in bytes of the metacontent. |
1287 | | % |
1288 | | % o metacontent: read these metacontent from the pixel cache. |
1289 | | % |
1290 | | */ |
1291 | | MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent( |
1292 | | DistributeCacheInfo *server_info,const RectangleInfo *region, |
1293 | | const MagickSizeType length,unsigned char *metacontent) |
1294 | 0 | { |
1295 | 0 | MagickOffsetType |
1296 | 0 | count; |
1297 | |
|
1298 | 0 | unsigned char |
1299 | 0 | message[MagickPathExtent], |
1300 | 0 | *p; |
1301 | | |
1302 | | /* |
1303 | | Read distributed pixel cache metacontent. |
1304 | | */ |
1305 | 0 | assert(server_info != (DistributeCacheInfo *) NULL); |
1306 | 0 | assert(server_info->signature == MagickCoreSignature); |
1307 | 0 | assert(region != (RectangleInfo *) NULL); |
1308 | 0 | assert(metacontent != (unsigned char *) NULL); |
1309 | 0 | if (length > (MagickSizeType) MAGICK_SSIZE_MAX) |
1310 | 0 | return(-1); |
1311 | 0 | p=message; |
1312 | 0 | *p++='R'; |
1313 | 0 | (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); |
1314 | 0 | p+=(ptrdiff_t) sizeof(server_info->session_key); |
1315 | 0 | (void) memcpy(p,®ion->width,sizeof(region->width)); |
1316 | 0 | p+=(ptrdiff_t) sizeof(region->width); |
1317 | 0 | (void) memcpy(p,®ion->height,sizeof(region->height)); |
1318 | 0 | p+=(ptrdiff_t) sizeof(region->height); |
1319 | 0 | (void) memcpy(p,®ion->x,sizeof(region->x)); |
1320 | 0 | p+=(ptrdiff_t) sizeof(region->x); |
1321 | 0 | (void) memcpy(p,®ion->y,sizeof(region->y)); |
1322 | 0 | p+=(ptrdiff_t) sizeof(region->y); |
1323 | 0 | (void) memcpy(p,&length,sizeof(length)); |
1324 | 0 | p+=(ptrdiff_t) sizeof(length); |
1325 | 0 | count=dpc_send(server_info->file,(MagickSizeType) (p-message),message); |
1326 | 0 | if (count != (MagickOffsetType) (p-message)) |
1327 | 0 | return(-1); |
1328 | 0 | return(dpc_read(server_info->file,length,metacontent)); |
1329 | 0 | } |
1330 | | |
1331 | | /* |
1332 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1333 | | % % |
1334 | | % % |
1335 | | % % |
1336 | | + R e a d D i s t r i b u t e P i x e l C a c h e P i x e l s % |
1337 | | % % |
1338 | | % % |
1339 | | % % |
1340 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1341 | | % |
1342 | | % ReadDistributePixelCachePixels() reads pixels from the specified region of |
1343 | | % the distributed pixel cache. |
1344 | | % |
1345 | | % The format of the ReadDistributePixelCachePixels method is: |
1346 | | % |
1347 | | % MagickOffsetType ReadDistributePixelCachePixels( |
1348 | | % DistributeCacheInfo *server_info,const RectangleInfo *region, |
1349 | | % const MagickSizeType length,unsigned char *magick_restrict pixels) |
1350 | | % |
1351 | | % A description of each parameter follows: |
1352 | | % |
1353 | | % o server_info: the distributed cache info. |
1354 | | % |
1355 | | % o image: the image. |
1356 | | % |
1357 | | % o region: read the pixels from this region of the image. |
1358 | | % |
1359 | | % o length: the length in bytes of the pixels. |
1360 | | % |
1361 | | % o pixels: read these pixels from the pixel cache. |
1362 | | % |
1363 | | */ |
1364 | | MagickPrivate MagickOffsetType ReadDistributePixelCachePixels( |
1365 | | DistributeCacheInfo *server_info,const RectangleInfo *region, |
1366 | | const MagickSizeType length,unsigned char *magick_restrict pixels) |
1367 | 0 | { |
1368 | 0 | MagickOffsetType |
1369 | 0 | count; |
1370 | |
|
1371 | 0 | unsigned char |
1372 | 0 | message[MagickPathExtent], |
1373 | 0 | *p; |
1374 | | |
1375 | | /* |
1376 | | Read distributed pixel cache pixels. |
1377 | | */ |
1378 | 0 | assert(server_info != (DistributeCacheInfo *) NULL); |
1379 | 0 | assert(server_info->signature == MagickCoreSignature); |
1380 | 0 | assert(region != (RectangleInfo *) NULL); |
1381 | 0 | assert(pixels != (unsigned char *) NULL); |
1382 | 0 | if (length > (MagickSizeType) MAGICK_SSIZE_MAX) |
1383 | 0 | return(-1); |
1384 | 0 | p=message; |
1385 | 0 | *p++='r'; |
1386 | 0 | (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); |
1387 | 0 | p+=(ptrdiff_t) sizeof(server_info->session_key); |
1388 | 0 | (void) memcpy(p,®ion->width,sizeof(region->width)); |
1389 | 0 | p+=(ptrdiff_t) sizeof(region->width); |
1390 | 0 | (void) memcpy(p,®ion->height,sizeof(region->height)); |
1391 | 0 | p+=(ptrdiff_t) sizeof(region->height); |
1392 | 0 | (void) memcpy(p,®ion->x,sizeof(region->x)); |
1393 | 0 | p+=(ptrdiff_t) sizeof(region->x); |
1394 | 0 | (void) memcpy(p,®ion->y,sizeof(region->y)); |
1395 | 0 | p+=(ptrdiff_t) sizeof(region->y); |
1396 | 0 | (void) memcpy(p,&length,sizeof(length)); |
1397 | 0 | p+=(ptrdiff_t) sizeof(length); |
1398 | 0 | count=dpc_send(server_info->file,(MagickSizeType) (p-message),message); |
1399 | 0 | if (count != (MagickOffsetType) (p-message)) |
1400 | 0 | return(-1); |
1401 | 0 | return(dpc_read(server_info->file,length,pixels)); |
1402 | 0 | } |
1403 | | |
1404 | | /* |
1405 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1406 | | % % |
1407 | | % % |
1408 | | % % |
1409 | | + R e l i n q u i s h D i s t r i b u t e P i x e l C a c h e % |
1410 | | % % |
1411 | | % % |
1412 | | % % |
1413 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1414 | | % |
1415 | | % RelinquishDistributePixelCache() frees resources acquired with |
1416 | | % OpenDistributePixelCache(). |
1417 | | % |
1418 | | % The format of the RelinquishDistributePixelCache method is: |
1419 | | % |
1420 | | % MagickBooleanType RelinquishDistributePixelCache( |
1421 | | % DistributeCacheInfo *server_info) |
1422 | | % |
1423 | | % A description of each parameter follows: |
1424 | | % |
1425 | | % o server_info: the distributed cache info. |
1426 | | % |
1427 | | */ |
1428 | | MagickPrivate MagickBooleanType RelinquishDistributePixelCache( |
1429 | | DistributeCacheInfo *server_info) |
1430 | 0 | { |
1431 | 0 | MagickBooleanType |
1432 | 0 | status; |
1433 | |
|
1434 | 0 | MagickOffsetType |
1435 | 0 | count; |
1436 | |
|
1437 | 0 | unsigned char |
1438 | 0 | message[MagickPathExtent], |
1439 | 0 | *p; |
1440 | | |
1441 | | /* |
1442 | | Delete distributed pixel cache. |
1443 | | */ |
1444 | 0 | assert(server_info != (DistributeCacheInfo *) NULL); |
1445 | 0 | assert(server_info->signature == MagickCoreSignature); |
1446 | 0 | p=message; |
1447 | 0 | *p++='d'; |
1448 | 0 | (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); |
1449 | 0 | p+=(ptrdiff_t) sizeof(server_info->session_key); |
1450 | 0 | count=dpc_send(server_info->file,(MagickSizeType) (p-message),message); |
1451 | 0 | if (count != (MagickOffsetType) (p-message)) |
1452 | 0 | return(MagickFalse); |
1453 | 0 | status=MagickFalse; |
1454 | 0 | count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status); |
1455 | 0 | if (count != (MagickOffsetType) sizeof(status)) |
1456 | 0 | return(MagickFalse); |
1457 | 0 | return(status); |
1458 | 0 | } |
1459 | | |
1460 | | /* |
1461 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1462 | | % % |
1463 | | % % |
1464 | | % % |
1465 | | + W r i t e D i s t r i b u t e P i x e l C a c h e M e t a c o n t e n t % |
1466 | | % % |
1467 | | % % |
1468 | | % % |
1469 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1470 | | % |
1471 | | % WriteDistributePixelCacheMetacontents() writes image metacontent to the |
1472 | | % specified region of the distributed pixel cache. |
1473 | | % |
1474 | | % The format of the WriteDistributePixelCacheMetacontents method is: |
1475 | | % |
1476 | | % MagickOffsetType WriteDistributePixelCacheMetacontents( |
1477 | | % DistributeCacheInfo *server_info,const RectangleInfo *region, |
1478 | | % const MagickSizeType length,const unsigned char *metacontent) |
1479 | | % |
1480 | | % A description of each parameter follows: |
1481 | | % |
1482 | | % o server_info: the distributed cache info. |
1483 | | % |
1484 | | % o image: the image. |
1485 | | % |
1486 | | % o region: write the metacontent to this region of the image. |
1487 | | % |
1488 | | % o length: the length in bytes of the metacontent. |
1489 | | % |
1490 | | % o metacontent: write these metacontent to the pixel cache. |
1491 | | % |
1492 | | */ |
1493 | | MagickPrivate MagickOffsetType WriteDistributePixelCacheMetacontent( |
1494 | | DistributeCacheInfo *server_info,const RectangleInfo *region, |
1495 | | const MagickSizeType length,const unsigned char *metacontent) |
1496 | 0 | { |
1497 | 0 | MagickOffsetType |
1498 | 0 | count; |
1499 | |
|
1500 | 0 | unsigned char |
1501 | 0 | message[MagickPathExtent], |
1502 | 0 | *p; |
1503 | | |
1504 | | /* |
1505 | | Write distributed pixel cache metacontent. |
1506 | | */ |
1507 | 0 | assert(server_info != (DistributeCacheInfo *) NULL); |
1508 | 0 | assert(server_info->signature == MagickCoreSignature); |
1509 | 0 | assert(region != (RectangleInfo *) NULL); |
1510 | 0 | assert(metacontent != (unsigned char *) NULL); |
1511 | 0 | if (length > (MagickSizeType) MAGICK_SSIZE_MAX) |
1512 | 0 | return(-1); |
1513 | 0 | p=message; |
1514 | 0 | *p++='W'; |
1515 | 0 | (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); |
1516 | 0 | p+=(ptrdiff_t) sizeof(server_info->session_key); |
1517 | 0 | (void) memcpy(p,®ion->width,sizeof(region->width)); |
1518 | 0 | p+=(ptrdiff_t) sizeof(region->width); |
1519 | 0 | (void) memcpy(p,®ion->height,sizeof(region->height)); |
1520 | 0 | p+=(ptrdiff_t) sizeof(region->height); |
1521 | 0 | (void) memcpy(p,®ion->x,sizeof(region->x)); |
1522 | 0 | p+=(ptrdiff_t) sizeof(region->x); |
1523 | 0 | (void) memcpy(p,®ion->y,sizeof(region->y)); |
1524 | 0 | p+=(ptrdiff_t) sizeof(region->y); |
1525 | 0 | (void) memcpy(p,&length,sizeof(length)); |
1526 | 0 | p+=(ptrdiff_t) sizeof(length); |
1527 | 0 | count=dpc_send(server_info->file,(MagickSizeType) (p-message),message); |
1528 | 0 | if (count != (MagickOffsetType) (p-message)) |
1529 | 0 | return(-1); |
1530 | 0 | return(dpc_send(server_info->file,length,metacontent)); |
1531 | 0 | } |
1532 | | |
1533 | | /* |
1534 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1535 | | % % |
1536 | | % % |
1537 | | % % |
1538 | | + W r i t e D i s t r i b u t e P i x e l C a c h e P i x e l s % |
1539 | | % % |
1540 | | % % |
1541 | | % % |
1542 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1543 | | % |
1544 | | % WriteDistributePixelCachePixels() writes image pixels to the specified |
1545 | | % region of the distributed pixel cache. |
1546 | | % |
1547 | | % The format of the WriteDistributePixelCachePixels method is: |
1548 | | % |
1549 | | % MagickBooleanType WriteDistributePixelCachePixels( |
1550 | | % DistributeCacheInfo *server_info,const RectangleInfo *region, |
1551 | | % const MagickSizeType length, |
1552 | | % const unsigned char *magick_restrict pixels) |
1553 | | % |
1554 | | % A description of each parameter follows: |
1555 | | % |
1556 | | % o server_info: the distributed cache info. |
1557 | | % |
1558 | | % o image: the image. |
1559 | | % |
1560 | | % o region: write the pixels to this region of the image. |
1561 | | % |
1562 | | % o length: the length in bytes of the pixels. |
1563 | | % |
1564 | | % o pixels: write these pixels to the pixel cache. |
1565 | | % |
1566 | | */ |
1567 | | MagickPrivate MagickOffsetType WriteDistributePixelCachePixels( |
1568 | | DistributeCacheInfo *server_info,const RectangleInfo *region, |
1569 | | const MagickSizeType length,const unsigned char *magick_restrict pixels) |
1570 | 0 | { |
1571 | 0 | MagickOffsetType |
1572 | 0 | count; |
1573 | |
|
1574 | 0 | unsigned char |
1575 | 0 | message[MagickPathExtent], |
1576 | 0 | *p; |
1577 | | |
1578 | | /* |
1579 | | Write distributed pixel cache pixels. |
1580 | | */ |
1581 | 0 | assert(server_info != (DistributeCacheInfo *) NULL); |
1582 | 0 | assert(server_info->signature == MagickCoreSignature); |
1583 | 0 | assert(region != (RectangleInfo *) NULL); |
1584 | 0 | assert(pixels != (const unsigned char *) NULL); |
1585 | 0 | if (length > (MagickSizeType) MAGICK_SSIZE_MAX) |
1586 | 0 | return(-1); |
1587 | 0 | p=message; |
1588 | 0 | *p++='w'; |
1589 | 0 | (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); |
1590 | 0 | p+=(ptrdiff_t) sizeof(server_info->session_key); |
1591 | 0 | (void) memcpy(p,®ion->width,sizeof(region->width)); |
1592 | 0 | p+=(ptrdiff_t) sizeof(region->width); |
1593 | 0 | (void) memcpy(p,®ion->height,sizeof(region->height)); |
1594 | 0 | p+=(ptrdiff_t) sizeof(region->height); |
1595 | 0 | (void) memcpy(p,®ion->x,sizeof(region->x)); |
1596 | 0 | p+=(ptrdiff_t) sizeof(region->x); |
1597 | 0 | (void) memcpy(p,®ion->y,sizeof(region->y)); |
1598 | 0 | p+=(ptrdiff_t) sizeof(region->y); |
1599 | 0 | (void) memcpy(p,&length,sizeof(length)); |
1600 | 0 | p+=(ptrdiff_t) sizeof(length); |
1601 | 0 | count=dpc_send(server_info->file,(MagickSizeType) (p-message),message); |
1602 | 0 | if (count != (MagickOffsetType) (p-message)) |
1603 | 0 | return(-1); |
1604 | 0 | return(dpc_send(server_info->file,length,pixels)); |
1605 | 0 | } |