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