PNG  IHDR* pHYs+ IDATx]n#; cdLb Ǚ[at¤_:uP}>!Usă cag޿ ֵNu`ݼTâabO7uL&y^wFٝA"l[|ŲHLN밪4*sG3|Dv}?+y߉{OuOAt4Jj.u]Gz*҉sP'VQKbA1u\`& Af;HWj hsO;ogTu uj7S3/QzUr&wS`M$X_L7r2;aE+ώ%vikDA:dR+%KzƉo>eOth$z%: :{WwaQ:wz%4foɹE[9<]#ERINƻv溂E%P1i01 |Jvҗ&{b?9g=^wζXn/lK::90KwrюO\!ջ3uzuGv^;騢wq<Iatv09:tt~hEG`v;3@MNZD.1]L:{ծI3`L(÷ba")Y.iljCɄae#I"1 `3*Bdz>j<fU40⨬%O$3cGt]j%Fߠ_twJ;ABU8vP3uEԑwQ V:h%))LfraqX-ۿX]v-\9I gl8tzX ]ecm)-cgʒ#Uw=Wlێn(0hPP/ӨtQ“&J35 $=]r1{tLuǮ*i0_;NƝ8;-vݏr8+U-kruȕYr0RnC]*ެ(M:]gE;{]tg(#ZJ9y>utRDRMdr9㪩̞zֹb<ģ&wzJM"iI( .ꮅX)Qw:9,i좜\Ԛi7&N0:asϓc];=ΗOӣ APqz93 y $)A*kVHZwBƺnWNaby>XMN*45~ղM6Nvm;A=jֲ.~1}(9`KJ/V F9[=`~[;sRuk]rєT!)iQO)Y$V ی ۤmzWz5IM Zb )ˆC`6 rRa}qNmUfDsWuˤV{ Pݝ'=Kֳbg,UҘVz2ﴻnjNgBb{? ߮tcsͻQuxVCIY۠:(V뺕 ٥2;t`@Fo{Z9`;]wMzU~%UA蛚dI vGq\r82iu +St`cR.6U/M9IENDB`/////////////////////////////////////////////////////////////////////////////// // /// \file 04_compress_easy_mt.c /// \brief Compress in multi-call mode using LZMA2 in multi-threaded mode /// /// Usage: ./04_compress_easy_mt < INFILE > OUTFILE /// /// Example: ./04_compress_easy_mt < foo > foo.xz // // Author: Lasse Collin // // This file has been put into the public domain. // You can do whatever you want with this file. // /////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include static bool init_encoder(lzma_stream *strm) { // The threaded encoder takes the options as pointer to // a lzma_mt structure. lzma_mt mt = { // No flags are needed. .flags = 0, // Let liblzma determine a sane block size. .block_size = 0, // Use no timeout for lzma_code() calls by setting timeout // to zero. That is, sometimes lzma_code() might block for // a long time (from several seconds to even minutes). // If this is not OK, for example due to progress indicator // needing updates, specify a timeout in milliseconds here. // See the documentation of lzma_mt in lzma/container.h for // information how to choose a reasonable timeout. .timeout = 0, // Use the default preset (6) for LZMA2. // To use a preset, filters must be set to NULL. .preset = LZMA_PRESET_DEFAULT, .filters = NULL, // Use CRC64 for integrity checking. See also // 01_compress_easy.c about choosing the integrity check. .check = LZMA_CHECK_CRC64, }; // Detect how many threads the CPU supports. mt.threads = lzma_cputhreads(); // If the number of CPU cores/threads cannot be detected, // use one thread. Note that this isn't the same as the normal // single-threaded mode as this will still split the data into // blocks and use more RAM than the normal single-threaded mode. // You may want to consider using lzma_easy_encoder() or // lzma_stream_encoder() instead of lzma_stream_encoder_mt() if // lzma_cputhreads() returns 0 or 1. if (mt.threads == 0) mt.threads = 1; // If the number of CPU cores/threads exceeds threads_max, // limit the number of threads to keep memory usage lower. // The number 8 is arbitrarily chosen and may be too low or // high depending on the compression preset and the computer // being used. // // FIXME: A better way could be to check the amount of RAM // (or available RAM) and use lzma_stream_encoder_mt_memusage() // to determine if the number of threads should be reduced. const uint32_t threads_max = 8; if (mt.threads > threads_max) mt.threads = threads_max; // Initialize the threaded encoder. lzma_ret ret = lzma_stream_encoder_mt(strm, &mt); if (ret == LZMA_OK) return true; const char *msg; switch (ret) { case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break; case LZMA_OPTIONS_ERROR: // We are no longer using a plain preset so this error // message has been edited accordingly compared to // 01_compress_easy.c. msg = "Specified filter chain is not supported"; break; case LZMA_UNSUPPORTED_CHECK: msg = "Specified integrity check is not supported"; break; default: msg = "Unknown error, possibly a bug"; break; } fprintf(stderr, "Error initializing the encoder: %s (error code %u)\n", msg, ret); return false; } // This function is identical to the one in 01_compress_easy.c. static bool compress(lzma_stream *strm, FILE *infile, FILE *outfile) { lzma_action action = LZMA_RUN; uint8_t inbuf[BUFSIZ]; uint8_t outbuf[BUFSIZ]; strm->next_in = NULL; strm->avail_in = 0; strm->next_out = outbuf; strm->avail_out = sizeof(outbuf); while (true) { if (strm->avail_in == 0 && !feof(infile)) { strm->next_in = inbuf; strm->avail_in = fread(inbuf, 1, sizeof(inbuf), infile); if (ferror(infile)) { fprintf(stderr, "Read error: %s\n", strerror(errno)); return false; } if (feof(infile)) action = LZMA_FINISH; } lzma_ret ret = lzma_code(strm, action); if (strm->avail_out == 0 || ret == LZMA_STREAM_END) { size_t write_size = sizeof(outbuf) - strm->avail_out; if (fwrite(outbuf, 1, write_size, outfile) != write_size) { fprintf(stderr, "Write error: %s\n", strerror(errno)); return false; } strm->next_out = outbuf; strm->avail_out = sizeof(outbuf); } if (ret != LZMA_OK) { if (ret == LZMA_STREAM_END) return true; const char *msg; switch (ret) { case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break; case LZMA_DATA_ERROR: msg = "File size limits exceeded"; break; default: msg = "Unknown error, possibly a bug"; break; } fprintf(stderr, "Encoder error: %s (error code %u)\n", msg, ret); return false; } } } extern int main(void) { lzma_stream strm = LZMA_STREAM_INIT; bool success = init_encoder(&strm); if (success) success = compress(&strm, stdin, stdout); lzma_end(&strm); if (fclose(stdout)) { fprintf(stderr, "Write error: %s\n", strerror(errno)); success = false; } return success ? EXIT_SUCCESS : EXIT_FAILURE; }