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