blosc.c 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028
  1. /*********************************************************************
  2. Blosc - Blocked Shuffling and Compression Library
  3. Author: Francesc Alted <francesc@blosc.org>
  4. Creation date: 2009-05-20
  5. See LICENSES/BLOSC.txt for details about copyright and rights to use.
  6. **********************************************************************/
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <errno.h>
  10. #include <string.h>
  11. #include <sys/types.h>
  12. #include <sys/stat.h>
  13. #include <assert.h>
  14. #if defined(USING_CMAKE)
  15. #include "config.h"
  16. #endif /* USING_CMAKE */
  17. #include "blosc.h"
  18. #include "shuffle.h"
  19. #include "blosclz.h"
  20. #if defined(HAVE_LZ4)
  21. #include "lz4.h"
  22. #include "lz4hc.h"
  23. #endif /* HAVE_LZ4 */
  24. #if defined(HAVE_SNAPPY)
  25. #include "snappy-c.h"
  26. #endif /* HAVE_SNAPPY */
  27. #if defined(HAVE_ZLIB)
  28. #include "zlib.h"
  29. #endif /* HAVE_ZLIB */
  30. #if defined(_WIN32) && !defined(__MINGW32__)
  31. #include <windows.h>
  32. #include <malloc.h>
  33. /* stdint.h only available in VS2010 (VC++ 16.0) and newer */
  34. #if defined(_MSC_VER) && _MSC_VER < 1600
  35. #include "win32/stdint-windows.h"
  36. #else
  37. #include <stdint.h>
  38. #endif
  39. #include <process.h>
  40. #define getpid _getpid
  41. #else
  42. #include <stdint.h>
  43. #include <unistd.h>
  44. #include <inttypes.h>
  45. #endif /* _WIN32 */
  46. #if defined(_WIN32) && !defined(__GNUC__)
  47. #include "win32/pthread.h"
  48. #include "win32/pthread.c"
  49. #else
  50. #include <pthread.h>
  51. #endif
  52. /* If C11 is supported, use it's built-in aligned allocation. */
  53. #if __STDC_VERSION__ >= 201112L
  54. #include <stdalign.h>
  55. #endif
  56. /* Some useful units */
  57. #define KB 1024
  58. #define MB (1024*KB)
  59. /* Minimum buffer size to be compressed */
  60. #define MIN_BUFFERSIZE 128 /* Cannot be smaller than 66 */
  61. /* The maximum number of splits in a block for compression */
  62. #define MAX_SPLITS 16 /* Cannot be larger than 128 */
  63. /* The size of L1 cache. 32 KB is quite common nowadays. */
  64. #define L1 (32*KB)
  65. /* Have problems using posix barriers when symbol value is 200112L */
  66. /* This requires more investigation, but will work for the moment */
  67. #if defined(_POSIX_BARRIERS) && ( (_POSIX_BARRIERS - 20012L) >= 0 && _POSIX_BARRIERS != 200112L)
  68. #define _POSIX_BARRIERS_MINE
  69. #endif
  70. /* Synchronization variables */
  71. struct blosc_context {
  72. int32_t compress; /* 1 if we are doing compression 0 if decompress */
  73. const uint8_t* src;
  74. uint8_t* dest; /* The current pos in the destination buffer */
  75. uint8_t* header_flags; /* Flags for header. Currently booked:
  76. - 0: byte-shuffled?
  77. - 1: memcpy'ed?
  78. - 2: bit-shuffled? */
  79. int32_t sourcesize; /* Number of bytes in source buffer (or uncompressed bytes in compressed file) */
  80. int32_t nblocks; /* Number of total blocks in buffer */
  81. int32_t leftover; /* Extra bytes at end of buffer */
  82. int32_t blocksize; /* Length of the block in bytes */
  83. int32_t typesize; /* Type size */
  84. int32_t num_output_bytes; /* Counter for the number of output bytes */
  85. int32_t destsize; /* Maximum size for destination buffer */
  86. uint8_t* bstarts; /* Start of the buffer past header info */
  87. int32_t compcode; /* Compressor code to use */
  88. int clevel; /* Compression level (1-9) */
  89. /* Threading */
  90. int32_t numthreads;
  91. int32_t threads_started;
  92. int32_t end_threads;
  93. pthread_t threads[BLOSC_MAX_THREADS];
  94. int32_t tids[BLOSC_MAX_THREADS];
  95. pthread_mutex_t count_mutex;
  96. #ifdef _POSIX_BARRIERS_MINE
  97. pthread_barrier_t barr_init;
  98. pthread_barrier_t barr_finish;
  99. #else
  100. int32_t count_threads;
  101. pthread_mutex_t count_threads_mutex;
  102. pthread_cond_t count_threads_cv;
  103. #endif
  104. #if !defined(_WIN32)
  105. pthread_attr_t ct_attr; /* creation time attrs for threads */
  106. #endif
  107. int32_t thread_giveup_code; /* error code when give up */
  108. int32_t thread_nblock; /* block counter */
  109. };
  110. struct thread_context {
  111. struct blosc_context* parent_context;
  112. int32_t tid;
  113. uint8_t* tmp;
  114. uint8_t* tmp2;
  115. uint8_t* tmp3;
  116. int32_t tmpblocksize; /* Used to keep track of how big the temporary buffers are */
  117. };
  118. /* Global context for non-contextual API */
  119. static struct blosc_context* g_global_context;
  120. static pthread_mutex_t global_comp_mutex;
  121. static int32_t g_compressor = BLOSC_BLOSCLZ; /* the compressor to use by default */
  122. static int32_t g_threads = 1;
  123. static int32_t g_force_blocksize = 0;
  124. static int32_t g_initlib = 0;
  125. /* Wrapped function to adjust the number of threads used by blosc */
  126. int blosc_set_nthreads_(struct blosc_context*);
  127. /* Releases the global threadpool */
  128. int blosc_release_threadpool(struct blosc_context* context);
  129. /* Macros for synchronization */
  130. /* Wait until all threads are initialized */
  131. #ifdef _POSIX_BARRIERS_MINE
  132. #define WAIT_INIT(RET_VAL, CONTEXT_PTR) \
  133. rc = pthread_barrier_wait(&CONTEXT_PTR->barr_init); \
  134. if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) { \
  135. printf("Could not wait on barrier (init): %d\n", rc); \
  136. return((RET_VAL)); \
  137. }
  138. #else
  139. #define WAIT_INIT(RET_VAL, CONTEXT_PTR) \
  140. pthread_mutex_lock(&CONTEXT_PTR->count_threads_mutex); \
  141. if (CONTEXT_PTR->count_threads < CONTEXT_PTR->numthreads) { \
  142. CONTEXT_PTR->count_threads++; \
  143. pthread_cond_wait(&CONTEXT_PTR->count_threads_cv, &CONTEXT_PTR->count_threads_mutex); \
  144. } \
  145. else { \
  146. pthread_cond_broadcast(&CONTEXT_PTR->count_threads_cv); \
  147. } \
  148. pthread_mutex_unlock(&CONTEXT_PTR->count_threads_mutex);
  149. #endif
  150. /* Wait for all threads to finish */
  151. #ifdef _POSIX_BARRIERS_MINE
  152. #define WAIT_FINISH(RET_VAL, CONTEXT_PTR) \
  153. rc = pthread_barrier_wait(&CONTEXT_PTR->barr_finish); \
  154. if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) { \
  155. printf("Could not wait on barrier (finish)\n"); \
  156. return((RET_VAL)); \
  157. }
  158. #else
  159. #define WAIT_FINISH(RET_VAL, CONTEXT_PTR) \
  160. pthread_mutex_lock(&CONTEXT_PTR->count_threads_mutex); \
  161. if (CONTEXT_PTR->count_threads > 0) { \
  162. CONTEXT_PTR->count_threads--; \
  163. pthread_cond_wait(&CONTEXT_PTR->count_threads_cv, &CONTEXT_PTR->count_threads_mutex); \
  164. } \
  165. else { \
  166. pthread_cond_broadcast(&CONTEXT_PTR->count_threads_cv); \
  167. } \
  168. pthread_mutex_unlock(&CONTEXT_PTR->count_threads_mutex);
  169. #endif
  170. /* A function for aligned malloc that is portable */
  171. static uint8_t *my_malloc(size_t size)
  172. {
  173. void *block = NULL;
  174. int res = 0;
  175. /* Do an alignment to 32 bytes because AVX2 is supported */
  176. #if _ISOC11_SOURCE
  177. /* C11 aligned allocation. 'size' must be a multiple of the alignment. */
  178. block = aligned_alloc(32, size);
  179. #elif defined(_WIN32)
  180. /* A (void *) cast needed for avoiding a warning with MINGW :-/ */
  181. block = (void *)_aligned_malloc(size, 32);
  182. #elif defined __APPLE__
  183. /* Mac OS X guarantees 16-byte alignment in small allocs */
  184. block = malloc(size);
  185. #elif _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
  186. /* Platform does have an implementation of posix_memalign */
  187. res = posix_memalign(&block, 32, size);
  188. #else
  189. block = malloc(size);
  190. #endif /* _WIN32 */
  191. if (block == NULL || res != 0) {
  192. printf("Error allocating memory!");
  193. return NULL;
  194. }
  195. return (uint8_t *)block;
  196. }
  197. /* Release memory booked by my_malloc */
  198. static void my_free(void *block)
  199. {
  200. #if defined(_WIN32)
  201. _aligned_free(block);
  202. #else
  203. free(block);
  204. #endif /* _WIN32 */
  205. }
  206. /* Copy 4 bytes from `*pa` to int32_t, changing endianness if necessary. */
  207. static int32_t sw32_(const uint8_t *pa)
  208. {
  209. int32_t idest;
  210. uint8_t *dest = (uint8_t *)&idest;
  211. int i = 1; /* for big/little endian detection */
  212. char *p = (char *)&i;
  213. if (p[0] != 1) {
  214. /* big endian */
  215. dest[0] = pa[3];
  216. dest[1] = pa[2];
  217. dest[2] = pa[1];
  218. dest[3] = pa[0];
  219. }
  220. else {
  221. /* little endian */
  222. dest[0] = pa[0];
  223. dest[1] = pa[1];
  224. dest[2] = pa[2];
  225. dest[3] = pa[3];
  226. }
  227. return idest;
  228. }
  229. /* Copy 4 bytes from `*pa` to `*dest`, changing endianness if necessary. */
  230. static void _sw32(uint8_t* dest, int32_t a)
  231. {
  232. uint8_t *pa = (uint8_t *)&a;
  233. int i = 1; /* for big/little endian detection */
  234. char *p = (char *)&i;
  235. if (p[0] != 1) {
  236. /* big endian */
  237. dest[0] = pa[3];
  238. dest[1] = pa[2];
  239. dest[2] = pa[1];
  240. dest[3] = pa[0];
  241. }
  242. else {
  243. /* little endian */
  244. dest[0] = pa[0];
  245. dest[1] = pa[1];
  246. dest[2] = pa[2];
  247. dest[3] = pa[3];
  248. }
  249. }
  250. /*
  251. * Conversion routines between compressor and compression libraries
  252. */
  253. /* Return the library code associated with the compressor name */
  254. static int compname_to_clibcode(const char *compname)
  255. {
  256. if (strcmp(compname, BLOSC_BLOSCLZ_COMPNAME) == 0)
  257. return BLOSC_BLOSCLZ_LIB;
  258. if (strcmp(compname, BLOSC_LZ4_COMPNAME) == 0)
  259. return BLOSC_LZ4_LIB;
  260. if (strcmp(compname, BLOSC_LZ4HC_COMPNAME) == 0)
  261. return BLOSC_LZ4_LIB;
  262. if (strcmp(compname, BLOSC_SNAPPY_COMPNAME) == 0)
  263. return BLOSC_SNAPPY_LIB;
  264. if (strcmp(compname, BLOSC_ZLIB_COMPNAME) == 0)
  265. return BLOSC_ZLIB_LIB;
  266. return -1;
  267. }
  268. /* Return the library name associated with the compressor code */
  269. static char *clibcode_to_clibname(int clibcode)
  270. {
  271. if (clibcode == BLOSC_BLOSCLZ_LIB) return BLOSC_BLOSCLZ_LIBNAME;
  272. if (clibcode == BLOSC_LZ4_LIB) return BLOSC_LZ4_LIBNAME;
  273. if (clibcode == BLOSC_SNAPPY_LIB) return BLOSC_SNAPPY_LIBNAME;
  274. if (clibcode == BLOSC_ZLIB_LIB) return BLOSC_ZLIB_LIBNAME;
  275. return NULL; /* should never happen */
  276. }
  277. /*
  278. * Conversion routines between compressor names and compressor codes
  279. */
  280. /* Get the compressor name associated with the compressor code */
  281. int blosc_compcode_to_compname(int compcode, char **compname)
  282. {
  283. int code = -1; /* -1 means non-existent compressor code */
  284. char *name = NULL;
  285. /* Map the compressor code */
  286. if (compcode == BLOSC_BLOSCLZ)
  287. name = BLOSC_BLOSCLZ_COMPNAME;
  288. else if (compcode == BLOSC_LZ4)
  289. name = BLOSC_LZ4_COMPNAME;
  290. else if (compcode == BLOSC_LZ4HC)
  291. name = BLOSC_LZ4HC_COMPNAME;
  292. else if (compcode == BLOSC_SNAPPY)
  293. name = BLOSC_SNAPPY_COMPNAME;
  294. else if (compcode == BLOSC_ZLIB)
  295. name = BLOSC_ZLIB_COMPNAME;
  296. *compname = name;
  297. /* Guess if there is support for this code */
  298. if (compcode == BLOSC_BLOSCLZ)
  299. code = BLOSC_BLOSCLZ;
  300. #if defined(HAVE_LZ4)
  301. else if (compcode == BLOSC_LZ4)
  302. code = BLOSC_LZ4;
  303. else if (compcode == BLOSC_LZ4HC)
  304. code = BLOSC_LZ4HC;
  305. #endif /* HAVE_LZ4 */
  306. #if defined(HAVE_SNAPPY)
  307. else if (compcode == BLOSC_SNAPPY)
  308. code = BLOSC_SNAPPY;
  309. #endif /* HAVE_SNAPPY */
  310. #if defined(HAVE_ZLIB)
  311. else if (compcode == BLOSC_ZLIB)
  312. code = BLOSC_ZLIB;
  313. #endif /* HAVE_ZLIB */
  314. return code;
  315. }
  316. /* Get the compressor code for the compressor name. -1 if it is not available */
  317. int blosc_compname_to_compcode(const char *compname)
  318. {
  319. int code = -1; /* -1 means non-existent compressor code */
  320. if (strcmp(compname, BLOSC_BLOSCLZ_COMPNAME) == 0) {
  321. code = BLOSC_BLOSCLZ;
  322. }
  323. #if defined(HAVE_LZ4)
  324. else if (strcmp(compname, BLOSC_LZ4_COMPNAME) == 0) {
  325. code = BLOSC_LZ4;
  326. }
  327. else if (strcmp(compname, BLOSC_LZ4HC_COMPNAME) == 0) {
  328. code = BLOSC_LZ4HC;
  329. }
  330. #endif /* HAVE_LZ4 */
  331. #if defined(HAVE_SNAPPY)
  332. else if (strcmp(compname, BLOSC_SNAPPY_COMPNAME) == 0) {
  333. code = BLOSC_SNAPPY;
  334. }
  335. #endif /* HAVE_SNAPPY */
  336. #if defined(HAVE_ZLIB)
  337. else if (strcmp(compname, BLOSC_ZLIB_COMPNAME) == 0) {
  338. code = BLOSC_ZLIB;
  339. }
  340. #endif /* HAVE_ZLIB */
  341. return code;
  342. }
  343. #if defined(HAVE_LZ4)
  344. static int lz4_wrap_compress(const char* input, size_t input_length,
  345. char* output, size_t maxout, int accel)
  346. {
  347. int cbytes;
  348. cbytes = LZ4_compress_fast(input, output, (int)input_length, (int)maxout,
  349. accel);
  350. return cbytes;
  351. }
  352. static int lz4hc_wrap_compress(const char* input, size_t input_length,
  353. char* output, size_t maxout, int clevel)
  354. {
  355. int cbytes;
  356. if (input_length > (size_t)(2<<30))
  357. return -1; /* input larger than 1 GB is not supported */
  358. /* clevel for lz4hc goes up to 16, at least in LZ4 1.1.3 */
  359. cbytes = LZ4_compressHC2_limitedOutput(input, output, (int)input_length,
  360. (int)maxout, clevel*2-1);
  361. return cbytes;
  362. }
  363. static int lz4_wrap_decompress(const char* input, size_t compressed_length,
  364. char* output, size_t maxout)
  365. {
  366. size_t cbytes;
  367. cbytes = LZ4_decompress_fast(input, output, (int)maxout);
  368. if (cbytes != compressed_length) {
  369. return 0;
  370. }
  371. return (int)maxout;
  372. }
  373. #endif /* HAVE_LZ4 */
  374. #if defined(HAVE_SNAPPY)
  375. static int snappy_wrap_compress(const char* input, size_t input_length,
  376. char* output, size_t maxout)
  377. {
  378. snappy_status status;
  379. size_t cl = maxout;
  380. status = snappy_compress(input, input_length, output, &cl);
  381. if (status != SNAPPY_OK){
  382. return 0;
  383. }
  384. return (int)cl;
  385. }
  386. static int snappy_wrap_decompress(const char* input, size_t compressed_length,
  387. char* output, size_t maxout)
  388. {
  389. snappy_status status;
  390. size_t ul = maxout;
  391. status = snappy_uncompress(input, compressed_length, output, &ul);
  392. if (status != SNAPPY_OK){
  393. return 0;
  394. }
  395. return (int)ul;
  396. }
  397. #endif /* HAVE_SNAPPY */
  398. #if defined(HAVE_ZLIB)
  399. /* zlib is not very respectful with sharing name space with others.
  400. Fortunately, its names do not collide with those already in blosc. */
  401. static int zlib_wrap_compress(const char* input, size_t input_length,
  402. char* output, size_t maxout, int clevel)
  403. {
  404. int status;
  405. uLongf cl = maxout;
  406. status = compress2(
  407. (Bytef*)output, &cl, (Bytef*)input, (uLong)input_length, clevel);
  408. if (status != Z_OK){
  409. return 0;
  410. }
  411. return (int)cl;
  412. }
  413. static int zlib_wrap_decompress(const char* input, size_t compressed_length,
  414. char* output, size_t maxout)
  415. {
  416. int status;
  417. uLongf ul = maxout;
  418. status = uncompress(
  419. (Bytef*)output, &ul, (Bytef*)input, (uLong)compressed_length);
  420. if (status != Z_OK){
  421. return 0;
  422. }
  423. return (int)ul;
  424. }
  425. #endif /* HAVE_ZLIB */
  426. /* Compute acceleration for blosclz */
  427. static int get_accel(const struct blosc_context* context) {
  428. int32_t clevel = context->clevel;
  429. int32_t typesize = context->typesize;
  430. if (clevel == 9) {
  431. return 1;
  432. }
  433. if (context->compcode == BLOSC_BLOSCLZ) {
  434. /* Compute the power of 2. See:
  435. * http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/
  436. */
  437. int32_t tspow2 = ((typesize != 0) && !(typesize & (typesize - 1)));
  438. if (tspow2 && typesize < 32) {
  439. return 32;
  440. }
  441. }
  442. else if (context->compcode == BLOSC_LZ4) {
  443. /* This acceleration setting based on discussions held in:
  444. * https://groups.google.com/forum/#!topic/lz4c/zosy90P8MQw
  445. */
  446. return (10 - clevel);
  447. }
  448. return 1;
  449. }
  450. /* Shuffle & compress a single block */
  451. static int blosc_c(const struct blosc_context* context, int32_t blocksize,
  452. int32_t leftoverblock, int32_t ntbytes, int32_t maxbytes,
  453. const uint8_t *src, uint8_t *dest, uint8_t *tmp,
  454. uint8_t *tmp2)
  455. {
  456. int32_t j, neblock, nsplits;
  457. int32_t cbytes; /* number of compressed bytes in split */
  458. int32_t ctbytes = 0; /* number of compressed bytes in block */
  459. int32_t maxout;
  460. int32_t typesize = context->typesize;
  461. const uint8_t *_tmp = src;
  462. char *compname;
  463. int accel;
  464. int bscount;
  465. if (*(context->header_flags) & BLOSC_DOSHUFFLE & (typesize > 1)) {
  466. /* Byte shuffling only makes sense if typesize > 1 */
  467. shuffle(typesize, blocksize, src, tmp);
  468. _tmp = tmp;
  469. }
  470. /* We don't allow more than 1 filter at the same time (yet) */
  471. else if (*(context->header_flags) & BLOSC_DOBITSHUFFLE) {
  472. bscount = bitshuffle(typesize, blocksize, src, tmp, tmp2);
  473. if (bscount < 0)
  474. return bscount;
  475. _tmp = tmp;
  476. }
  477. /* Calculate acceleration for different compressors */
  478. accel = get_accel(context);
  479. /* Compress for each shuffled slice split for this block. */
  480. /* If typesize is too large, neblock is too small or we are in a
  481. leftover block, do not split at all. */
  482. if ((typesize <= MAX_SPLITS) && (blocksize/typesize) >= MIN_BUFFERSIZE &&
  483. (!leftoverblock)) {
  484. nsplits = typesize;
  485. }
  486. else {
  487. nsplits = 1;
  488. }
  489. neblock = blocksize / nsplits;
  490. for (j = 0; j < nsplits; j++) {
  491. dest += sizeof(int32_t);
  492. ntbytes += (int32_t)sizeof(int32_t);
  493. ctbytes += (int32_t)sizeof(int32_t);
  494. maxout = neblock;
  495. #if defined(HAVE_SNAPPY)
  496. if (context->compcode == BLOSC_SNAPPY) {
  497. /* TODO perhaps refactor this to keep the value stashed somewhere */
  498. maxout = snappy_max_compressed_length(neblock);
  499. }
  500. #endif /* HAVE_SNAPPY */
  501. if (ntbytes+maxout > maxbytes) {
  502. maxout = maxbytes - ntbytes; /* avoid buffer overrun */
  503. if (maxout <= 0) {
  504. return 0; /* non-compressible block */
  505. }
  506. }
  507. if (context->compcode == BLOSC_BLOSCLZ) {
  508. cbytes = blosclz_compress(context->clevel, _tmp+j*neblock, neblock,
  509. dest, maxout, accel);
  510. }
  511. #if defined(HAVE_LZ4)
  512. else if (context->compcode == BLOSC_LZ4) {
  513. cbytes = lz4_wrap_compress((char *)_tmp+j*neblock, (size_t)neblock,
  514. (char *)dest, (size_t)maxout, accel);
  515. }
  516. else if (context->compcode == BLOSC_LZ4HC) {
  517. cbytes = lz4hc_wrap_compress((char *)_tmp+j*neblock, (size_t)neblock,
  518. (char *)dest, (size_t)maxout,
  519. context->clevel);
  520. }
  521. #endif /* HAVE_LZ4 */
  522. #if defined(HAVE_SNAPPY)
  523. else if (context->compcode == BLOSC_SNAPPY) {
  524. cbytes = snappy_wrap_compress((char *)_tmp+j*neblock, (size_t)neblock,
  525. (char *)dest, (size_t)maxout);
  526. }
  527. #endif /* HAVE_SNAPPY */
  528. #if defined(HAVE_ZLIB)
  529. else if (context->compcode == BLOSC_ZLIB) {
  530. cbytes = zlib_wrap_compress((char *)_tmp+j*neblock, (size_t)neblock,
  531. (char *)dest, (size_t)maxout,
  532. context->clevel);
  533. }
  534. #endif /* HAVE_ZLIB */
  535. else {
  536. blosc_compcode_to_compname(context->compcode, &compname);
  537. fprintf(stderr, "Blosc has not been compiled with '%s' ", compname);
  538. fprintf(stderr, "compression support. Please use one having it.");
  539. return -5; /* signals no compression support */
  540. }
  541. if (cbytes > maxout) {
  542. /* Buffer overrun caused by compression (should never happen) */
  543. return -1;
  544. }
  545. else if (cbytes < 0) {
  546. /* cbytes should never be negative */
  547. return -2;
  548. }
  549. else if (cbytes == 0 || cbytes == neblock) {
  550. /* The compressor has been unable to compress data at all. */
  551. /* Before doing the copy, check that we are not running into a
  552. buffer overflow. */
  553. if ((ntbytes+neblock) > maxbytes) {
  554. return 0; /* Non-compressible data */
  555. }
  556. memcpy(dest, _tmp+j*neblock, neblock);
  557. cbytes = neblock;
  558. }
  559. _sw32(dest - 4, cbytes);
  560. dest += cbytes;
  561. ntbytes += cbytes;
  562. ctbytes += cbytes;
  563. } /* Closes j < nsplits */
  564. return ctbytes;
  565. }
  566. /* Decompress & unshuffle a single block */
  567. static int blosc_d(struct blosc_context* context, int32_t blocksize, int32_t leftoverblock,
  568. const uint8_t *src, uint8_t *dest, uint8_t *tmp, uint8_t *tmp2)
  569. {
  570. int32_t j, neblock, nsplits;
  571. int32_t nbytes; /* number of decompressed bytes in split */
  572. int32_t cbytes; /* number of compressed bytes in split */
  573. int32_t ctbytes = 0; /* number of compressed bytes in block */
  574. int32_t ntbytes = 0; /* number of uncompressed bytes in block */
  575. uint8_t *_tmp = dest;
  576. int32_t typesize = context->typesize;
  577. int32_t compformat;
  578. char *compname;
  579. int bscount;
  580. if ((*(context->header_flags) & BLOSC_DOSHUFFLE & (typesize > 1)) || \
  581. (*(context->header_flags) & BLOSC_DOBITSHUFFLE)) {
  582. _tmp = tmp;
  583. }
  584. compformat = (*(context->header_flags) & 0xe0) >> 5;
  585. /* Compress for each shuffled slice split for this block. */
  586. if ((typesize <= MAX_SPLITS) && (blocksize/typesize) >= MIN_BUFFERSIZE &&
  587. (!leftoverblock)) {
  588. nsplits = typesize;
  589. }
  590. else {
  591. nsplits = 1;
  592. }
  593. neblock = blocksize / nsplits;
  594. for (j = 0; j < nsplits; j++) {
  595. cbytes = sw32_(src); /* amount of compressed bytes */
  596. src += sizeof(int32_t);
  597. ctbytes += (int32_t)sizeof(int32_t);
  598. /* Uncompress */
  599. if (cbytes == neblock) {
  600. memcpy(_tmp, src, neblock);
  601. nbytes = neblock;
  602. }
  603. else {
  604. if (compformat == BLOSC_BLOSCLZ_FORMAT) {
  605. nbytes = blosclz_decompress(src, cbytes, _tmp, neblock);
  606. }
  607. #if defined(HAVE_LZ4)
  608. else if (compformat == BLOSC_LZ4_FORMAT) {
  609. nbytes = lz4_wrap_decompress((char *)src, (size_t)cbytes,
  610. (char*)_tmp, (size_t)neblock);
  611. }
  612. #endif /* HAVE_LZ4 */
  613. #if defined(HAVE_SNAPPY)
  614. else if (compformat == BLOSC_SNAPPY_FORMAT) {
  615. nbytes = snappy_wrap_decompress((char *)src, (size_t)cbytes,
  616. (char*)_tmp, (size_t)neblock);
  617. }
  618. #endif /* HAVE_SNAPPY */
  619. #if defined(HAVE_ZLIB)
  620. else if (compformat == BLOSC_ZLIB_FORMAT) {
  621. nbytes = zlib_wrap_decompress((char *)src, (size_t)cbytes,
  622. (char*)_tmp, (size_t)neblock);
  623. }
  624. #endif /* HAVE_ZLIB */
  625. else {
  626. compname = clibcode_to_clibname(compformat);
  627. fprintf(stderr,
  628. "Blosc has not been compiled with decompression "
  629. "support for '%s' format. ", compname);
  630. fprintf(stderr, "Please recompile for adding this support.\n");
  631. return -5; /* signals no decompression support */
  632. }
  633. /* Check that decompressed bytes number is correct */
  634. if (nbytes != neblock) {
  635. return -2;
  636. }
  637. }
  638. src += cbytes;
  639. ctbytes += cbytes;
  640. _tmp += nbytes;
  641. ntbytes += nbytes;
  642. } /* Closes j < nsplits */
  643. if (*(context->header_flags) & BLOSC_DOSHUFFLE & (typesize > 1)) {
  644. unshuffle(typesize, blocksize, tmp, dest);
  645. }
  646. else if (*(context->header_flags) & BLOSC_DOBITSHUFFLE) {
  647. bscount = bitunshuffle(typesize, blocksize, tmp, dest, tmp2);
  648. if (bscount < 0)
  649. return bscount;
  650. }
  651. /* Return the number of uncompressed bytes */
  652. return ntbytes;
  653. }
  654. /* Serial version for compression/decompression */
  655. static int serial_blosc(struct blosc_context* context)
  656. {
  657. int32_t j, bsize, leftoverblock;
  658. int32_t cbytes;
  659. int32_t ebsize = context->blocksize + context->typesize * (int32_t)sizeof(int32_t);
  660. int32_t ntbytes = context->num_output_bytes;
  661. uint8_t *tmp = my_malloc(context->blocksize + ebsize);
  662. uint8_t *tmp2 = tmp + context->blocksize;
  663. for (j = 0; j < context->nblocks; j++) {
  664. if (context->compress && !(*(context->header_flags) & BLOSC_MEMCPYED)) {
  665. _sw32(context->bstarts + j * 4, ntbytes);
  666. }
  667. bsize = context->blocksize;
  668. leftoverblock = 0;
  669. if ((j == context->nblocks - 1) && (context->leftover > 0)) {
  670. bsize = context->leftover;
  671. leftoverblock = 1;
  672. }
  673. if (context->compress) {
  674. if (*(context->header_flags) & BLOSC_MEMCPYED) {
  675. /* We want to memcpy only */
  676. memcpy(context->dest+BLOSC_MAX_OVERHEAD+j*context->blocksize,
  677. context->src+j*context->blocksize,
  678. bsize);
  679. cbytes = bsize;
  680. }
  681. else {
  682. /* Regular compression */
  683. cbytes = blosc_c(context, bsize, leftoverblock, ntbytes,
  684. context->destsize, context->src+j*context->blocksize,
  685. context->dest+ntbytes, tmp, tmp2);
  686. if (cbytes == 0) {
  687. ntbytes = 0; /* uncompressible data */
  688. break;
  689. }
  690. }
  691. }
  692. else {
  693. if (*(context->header_flags) & BLOSC_MEMCPYED) {
  694. /* We want to memcpy only */
  695. memcpy(context->dest+j*context->blocksize,
  696. context->src+BLOSC_MAX_OVERHEAD+j*context->blocksize,
  697. bsize);
  698. cbytes = bsize;
  699. }
  700. else {
  701. /* Regular decompression */
  702. cbytes = blosc_d(context, bsize, leftoverblock,
  703. context->src + sw32_(context->bstarts + j * 4),
  704. context->dest+j*context->blocksize, tmp, tmp2);
  705. }
  706. }
  707. if (cbytes < 0) {
  708. ntbytes = cbytes; /* error in blosc_c or blosc_d */
  709. break;
  710. }
  711. ntbytes += cbytes;
  712. }
  713. // Free temporaries
  714. my_free(tmp);
  715. return ntbytes;
  716. }
  717. /* Threaded version for compression/decompression */
  718. static int parallel_blosc(struct blosc_context* context)
  719. {
  720. int rc;
  721. /* Check whether we need to restart threads */
  722. blosc_set_nthreads_(context);
  723. /* Set sentinels */
  724. context->thread_giveup_code = 1;
  725. context->thread_nblock = -1;
  726. /* Synchronization point for all threads (wait for initialization) */
  727. WAIT_INIT(-1, context);
  728. /* Synchronization point for all threads (wait for finalization) */
  729. WAIT_FINISH(-1, context);
  730. if (context->thread_giveup_code > 0) {
  731. /* Return the total bytes (de-)compressed in threads */
  732. return context->num_output_bytes;
  733. }
  734. else {
  735. /* Compression/decompression gave up. Return error code. */
  736. return context->thread_giveup_code;
  737. }
  738. }
  739. /* Do the compression or decompression of the buffer depending on the
  740. global params. */
  741. static int do_job(struct blosc_context* context)
  742. {
  743. int32_t ntbytes;
  744. /* Run the serial version when nthreads is 1 or when the buffers are
  745. not much larger than blocksize */
  746. if (context->numthreads == 1 || (context->sourcesize / context->blocksize) <= 1) {
  747. ntbytes = serial_blosc(context);
  748. }
  749. else {
  750. ntbytes = parallel_blosc(context);
  751. }
  752. return ntbytes;
  753. }
  754. static int32_t compute_blocksize(struct blosc_context* context, int32_t clevel,
  755. int32_t typesize, int32_t nbytes,
  756. int32_t forced_blocksize)
  757. {
  758. int32_t blocksize;
  759. /* Protection against very small buffers */
  760. if (nbytes < (int32_t)typesize) {
  761. return 1;
  762. }
  763. blocksize = nbytes; /* Start by a whole buffer as blocksize */
  764. if (forced_blocksize) {
  765. blocksize = forced_blocksize;
  766. /* Check that forced blocksize is not too small */
  767. if (blocksize < MIN_BUFFERSIZE) {
  768. blocksize = MIN_BUFFERSIZE;
  769. }
  770. }
  771. else if (nbytes >= L1) {
  772. blocksize = L1;
  773. /* For Zlib, increase the block sizes in a factor of 8 because it
  774. is meant for compression large blocks (it shows a big overhead
  775. in compressing small ones). */
  776. if (context->compcode == BLOSC_ZLIB) {
  777. blocksize *= 8;
  778. }
  779. /* For LZ4HC, increase the block sizes in a factor of 8 because it
  780. is meant for compression large blocks (it shows a big overhead
  781. in compressing small ones). */
  782. if (context->compcode == BLOSC_LZ4HC) {
  783. blocksize *= 8;
  784. }
  785. if (clevel == 0) {
  786. blocksize /= 4;
  787. }
  788. else if (clevel <= 3) {
  789. blocksize /= 2;
  790. }
  791. else if (clevel <= 5) {
  792. blocksize *= 1;
  793. }
  794. else if (clevel <= 6) {
  795. blocksize *= 2;
  796. }
  797. else if (clevel < 9) {
  798. blocksize *= 4;
  799. }
  800. else {
  801. blocksize *= 16;
  802. }
  803. }
  804. /* Check that blocksize is not too large */
  805. if (blocksize > (int32_t)nbytes) {
  806. blocksize = nbytes;
  807. }
  808. /* blocksize *must absolutely* be a multiple of the typesize */
  809. if (blocksize > typesize) {
  810. blocksize = blocksize / typesize * typesize;
  811. }
  812. return blocksize;
  813. }
  814. static int initialize_context_compression(struct blosc_context* context,
  815. int clevel,
  816. int doshuffle,
  817. size_t typesize,
  818. size_t sourcesize,
  819. const void* src,
  820. void* dest,
  821. size_t destsize,
  822. int32_t compressor,
  823. int32_t blocksize,
  824. int32_t numthreads)
  825. {
  826. /* Set parameters */
  827. context->compress = 1;
  828. context->src = (const uint8_t*)src;
  829. context->dest = (uint8_t *)(dest);
  830. context->num_output_bytes = 0;
  831. context->destsize = (int32_t)destsize;
  832. context->sourcesize = sourcesize;
  833. context->typesize = typesize;
  834. context->compcode = compressor;
  835. context->numthreads = numthreads;
  836. context->end_threads = 0;
  837. context->clevel = clevel;
  838. /* Check buffer size limits */
  839. if (sourcesize > BLOSC_MAX_BUFFERSIZE) {
  840. /* If buffer is too large, give up. */
  841. fprintf(stderr, "Input buffer size cannot exceed %d bytes\n",
  842. BLOSC_MAX_BUFFERSIZE);
  843. return -1;
  844. }
  845. /* Compression level */
  846. if (clevel < 0 || clevel > 9) {
  847. /* If clevel not in 0..9, print an error */
  848. fprintf(stderr, "`clevel` parameter must be between 0 and 9!\n");
  849. return -10;
  850. }
  851. /* Shuffle */
  852. if (doshuffle != 0 && doshuffle != 1 && doshuffle != 2) {
  853. fprintf(stderr, "`shuffle` parameter must be either 0, 1 or 2!\n");
  854. return -10;
  855. }
  856. /* Check typesize limits */
  857. if (context->typesize > BLOSC_MAX_TYPESIZE) {
  858. /* If typesize is too large, treat buffer as an 1-byte stream. */
  859. context->typesize = 1;
  860. }
  861. /* Get the blocksize */
  862. context->blocksize = compute_blocksize(context, clevel, (int32_t)context->typesize, context->sourcesize, blocksize);
  863. /* Compute number of blocks in buffer */
  864. context->nblocks = context->sourcesize / context->blocksize;
  865. context->leftover = context->sourcesize % context->blocksize;
  866. context->nblocks = (context->leftover > 0) ? (context->nblocks + 1) : context->nblocks;
  867. return 1;
  868. }
  869. static int write_compression_header(struct blosc_context* context, int clevel, int doshuffle)
  870. {
  871. int32_t compformat;
  872. /* Write version header for this block */
  873. context->dest[0] = BLOSC_VERSION_FORMAT; /* blosc format version */
  874. /* Write compressor format */
  875. compformat = -1;
  876. switch (context->compcode)
  877. {
  878. case BLOSC_BLOSCLZ:
  879. compformat = BLOSC_BLOSCLZ_FORMAT;
  880. context->dest[1] = BLOSC_BLOSCLZ_VERSION_FORMAT; /* blosclz format version */
  881. break;
  882. #if defined(HAVE_LZ4)
  883. case BLOSC_LZ4:
  884. compformat = BLOSC_LZ4_FORMAT;
  885. context->dest[1] = BLOSC_LZ4_VERSION_FORMAT; /* lz4 format version */
  886. break;
  887. case BLOSC_LZ4HC:
  888. compformat = BLOSC_LZ4HC_FORMAT;
  889. context->dest[1] = BLOSC_LZ4HC_VERSION_FORMAT; /* lz4hc is the same as lz4 */
  890. break;
  891. #endif /* HAVE_LZ4 */
  892. #if defined(HAVE_SNAPPY)
  893. case BLOSC_SNAPPY:
  894. compformat = BLOSC_SNAPPY_FORMAT;
  895. context->dest[1] = BLOSC_SNAPPY_VERSION_FORMAT; /* snappy format version */
  896. break;
  897. #endif /* HAVE_SNAPPY */
  898. #if defined(HAVE_ZLIB)
  899. case BLOSC_ZLIB:
  900. compformat = BLOSC_ZLIB_FORMAT;
  901. context->dest[1] = BLOSC_ZLIB_VERSION_FORMAT; /* zlib format version */
  902. break;
  903. #endif /* HAVE_ZLIB */
  904. default:
  905. {
  906. char *compname;
  907. compname = clibcode_to_clibname(compformat);
  908. fprintf(stderr, "Blosc has not been compiled with '%s' ", compname);
  909. fprintf(stderr, "compression support. Please use one having it.");
  910. return -5; /* signals no compression support */
  911. break;
  912. }
  913. }
  914. context->header_flags = context->dest+2; /* flags */
  915. context->dest[2] = 0; /* zeroes flags */
  916. context->dest[3] = (uint8_t)context->typesize; /* type size */
  917. _sw32(context->dest + 4, context->sourcesize); /* size of the buffer */
  918. _sw32(context->dest + 8, context->blocksize); /* block size */
  919. context->bstarts = context->dest + 16; /* starts for every block */
  920. context->num_output_bytes = 16 + sizeof(int32_t)*context->nblocks; /* space for header and pointers */
  921. if (context->clevel == 0) {
  922. /* Compression level 0 means buffer to be memcpy'ed */
  923. *(context->header_flags) |= BLOSC_MEMCPYED;
  924. }
  925. if (context->sourcesize < MIN_BUFFERSIZE) {
  926. /* Buffer is too small. Try memcpy'ing. */
  927. *(context->header_flags) |= BLOSC_MEMCPYED;
  928. }
  929. if (doshuffle == BLOSC_SHUFFLE) {
  930. /* Byte-shuffle is active */
  931. *(context->header_flags) |= BLOSC_DOSHUFFLE; /* bit 0 set to one in flags */
  932. }
  933. if (doshuffle == BLOSC_BITSHUFFLE) {
  934. /* Bit-shuffle is active */
  935. *(context->header_flags) |= BLOSC_DOBITSHUFFLE; /* bit 2 set to one in flags */
  936. }
  937. *(context->header_flags) |= compformat << 5; /* compressor format start at bit 5 */
  938. return 1;
  939. }
  940. int blosc_compress_context(struct blosc_context* context)
  941. {
  942. int32_t ntbytes = 0;
  943. if (!(*(context->header_flags) & BLOSC_MEMCPYED)) {
  944. /* Do the actual compression */
  945. ntbytes = do_job(context);
  946. if (ntbytes < 0) {
  947. return -1;
  948. }
  949. if ((ntbytes == 0) && (context->sourcesize+BLOSC_MAX_OVERHEAD <= context->destsize)) {
  950. /* Last chance for fitting `src` buffer in `dest`. Update flags
  951. and do a memcpy later on. */
  952. *(context->header_flags) |= BLOSC_MEMCPYED;
  953. }
  954. }
  955. if (*(context->header_flags) & BLOSC_MEMCPYED) {
  956. if (context->sourcesize + BLOSC_MAX_OVERHEAD > context->destsize) {
  957. /* We are exceeding maximum output size */
  958. ntbytes = 0;
  959. }
  960. else {
  961. memcpy(context->dest+BLOSC_MAX_OVERHEAD, context->src,
  962. context->sourcesize);
  963. ntbytes = context->sourcesize + BLOSC_MAX_OVERHEAD;
  964. }
  965. }
  966. /* Set the number of compressed bytes in header */
  967. _sw32(context->dest + 12, ntbytes);
  968. assert(ntbytes <= context->destsize);
  969. return ntbytes;
  970. }
  971. /* The public routine for compression with context. */
  972. int blosc_compress_ctx(int clevel, int doshuffle, size_t typesize,
  973. size_t nbytes, const void* src, void* dest,
  974. size_t destsize, const char* compressor,
  975. size_t blocksize, int numinternalthreads)
  976. {
  977. int error, result;
  978. struct blosc_context context;
  979. context.threads_started = 0;
  980. error = initialize_context_compression(&context, clevel, doshuffle, typesize,
  981. nbytes, src, dest, destsize,
  982. blosc_compname_to_compcode(compressor),
  983. blocksize, numinternalthreads);
  984. if (error < 0) { return error; }
  985. error = write_compression_header(&context, clevel, doshuffle);
  986. if (error < 0) { return error; }
  987. result = blosc_compress_context(&context);
  988. if (numinternalthreads > 1)
  989. {
  990. blosc_release_threadpool(&context);
  991. }
  992. return result;
  993. }
  994. /* The public routine for compression. See blosc.h for docstrings. */
  995. int blosc_compress(int clevel, int doshuffle, size_t typesize, size_t nbytes,
  996. const void *src, void *dest, size_t destsize)
  997. {
  998. int error;
  999. int result;
  1000. char* envvar;
  1001. /* Check if should initialize */
  1002. if (!g_initlib) blosc_init();
  1003. /* Check for a BLOSC_CLEVEL environment variable */
  1004. envvar = getenv("BLOSC_CLEVEL");
  1005. if (envvar != NULL) {
  1006. long value;
  1007. value = strtol(envvar, NULL, 10);
  1008. if ((value != EINVAL) && (value >= 0)) {
  1009. clevel = (int)value;
  1010. }
  1011. }
  1012. /* Check for a BLOSC_SHUFFLE environment variable */
  1013. envvar = getenv("BLOSC_SHUFFLE");
  1014. if (envvar != NULL) {
  1015. if (strcmp(envvar, "NOSHUFFLE") == 0) {
  1016. doshuffle = BLOSC_NOSHUFFLE;
  1017. }
  1018. if (strcmp(envvar, "SHUFFLE") == 0) {
  1019. doshuffle = BLOSC_SHUFFLE;
  1020. }
  1021. if (strcmp(envvar, "BITSHUFFLE") == 0) {
  1022. doshuffle = BLOSC_BITSHUFFLE;
  1023. }
  1024. }
  1025. /* Check for a BLOSC_TYPESIZE environment variable */
  1026. envvar = getenv("BLOSC_TYPESIZE");
  1027. if (envvar != NULL) {
  1028. long value;
  1029. value = strtol(envvar, NULL, 10);
  1030. if ((value != EINVAL) && (value > 0)) {
  1031. typesize = (int)value;
  1032. }
  1033. }
  1034. /* Check for a BLOSC_COMPRESSOR environment variable */
  1035. envvar = getenv("BLOSC_COMPRESSOR");
  1036. if (envvar != NULL) {
  1037. result = blosc_set_compressor(envvar);
  1038. if (result < 0) { return result; }
  1039. }
  1040. /* Check for a BLOSC_COMPRESSOR environment variable */
  1041. envvar = getenv("BLOSC_BLOCKSIZE");
  1042. if (envvar != NULL) {
  1043. long blocksize;
  1044. blocksize = strtol(envvar, NULL, 10);
  1045. if ((blocksize != EINVAL) && (blocksize > 0)) {
  1046. blosc_set_blocksize((size_t)blocksize);
  1047. }
  1048. }
  1049. /* Check for a BLOSC_NTHREADS environment variable */
  1050. envvar = getenv("BLOSC_NTHREADS");
  1051. if (envvar != NULL) {
  1052. long nthreads;
  1053. nthreads = strtol(envvar, NULL, 10);
  1054. if ((nthreads != EINVAL) && (nthreads > 0)) {
  1055. result = blosc_set_nthreads((int)nthreads);
  1056. if (result < 0) { return result; }
  1057. }
  1058. }
  1059. /* Check for a BLOSC_NOLOCK environment variable. It is important
  1060. that this should be the last env var so that it can take the
  1061. previous ones into account */
  1062. envvar = getenv("BLOSC_NOLOCK");
  1063. if (envvar != NULL) {
  1064. char *compname;
  1065. blosc_compcode_to_compname(g_compressor, &compname);
  1066. result = blosc_compress_ctx(clevel, doshuffle, typesize,
  1067. nbytes, src, dest, destsize,
  1068. compname, g_force_blocksize, g_threads);
  1069. return result;
  1070. }
  1071. pthread_mutex_lock(&global_comp_mutex);
  1072. error = initialize_context_compression(g_global_context, clevel, doshuffle,
  1073. typesize, nbytes, src, dest, destsize,
  1074. g_compressor, g_force_blocksize,
  1075. g_threads);
  1076. if (error < 0) { return error; }
  1077. error = write_compression_header(g_global_context, clevel, doshuffle);
  1078. if (error < 0) { return error; }
  1079. result = blosc_compress_context(g_global_context);
  1080. pthread_mutex_unlock(&global_comp_mutex);
  1081. return result;
  1082. }
  1083. int blosc_run_decompression_with_context(struct blosc_context* context,
  1084. const void* src,
  1085. void* dest,
  1086. size_t destsize,
  1087. int numinternalthreads)
  1088. {
  1089. uint8_t version;
  1090. uint8_t versionlz;
  1091. uint32_t ctbytes;
  1092. int32_t ntbytes;
  1093. context->compress = 0;
  1094. context->src = (const uint8_t*)src;
  1095. context->dest = (uint8_t*)dest;
  1096. context->destsize = destsize;
  1097. context->num_output_bytes = 0;
  1098. context->numthreads = numinternalthreads;
  1099. context->end_threads = 0;
  1100. /* Read the header block */
  1101. version = context->src[0]; /* blosc format version */
  1102. versionlz = context->src[1]; /* blosclz format version */
  1103. context->header_flags = (uint8_t*)(context->src + 2); /* flags */
  1104. context->typesize = (int32_t)context->src[3]; /* typesize */
  1105. context->sourcesize = sw32_(context->src + 4); /* buffer size */
  1106. context->blocksize = sw32_(context->src + 8); /* block size */
  1107. ctbytes = sw32_(context->src + 12); /* compressed buffer size */
  1108. /* Unused values */
  1109. version += 0; /* shut up compiler warning */
  1110. versionlz += 0; /* shut up compiler warning */
  1111. ctbytes += 0; /* shut up compiler warning */
  1112. context->bstarts = (uint8_t*)(context->src + 16);
  1113. /* Compute some params */
  1114. /* Total blocks */
  1115. context->nblocks = context->sourcesize / context->blocksize;
  1116. context->leftover = context->sourcesize % context->blocksize;
  1117. context->nblocks = (context->leftover>0)? context->nblocks+1: context->nblocks;
  1118. /* Check that we have enough space to decompress */
  1119. if (context->sourcesize > (int32_t)destsize) {
  1120. return -1;
  1121. }
  1122. /* Check whether this buffer is memcpy'ed */
  1123. if (*(context->header_flags) & BLOSC_MEMCPYED) {
  1124. memcpy(dest, (uint8_t *)src+BLOSC_MAX_OVERHEAD, context->sourcesize);
  1125. ntbytes = context->sourcesize;
  1126. }
  1127. else {
  1128. /* Do the actual decompression */
  1129. ntbytes = do_job(context);
  1130. if (ntbytes < 0) {
  1131. return -1;
  1132. }
  1133. }
  1134. assert(ntbytes <= (int32_t)destsize);
  1135. return ntbytes;
  1136. }
  1137. /* The public routine for decompression with context. */
  1138. int blosc_decompress_ctx(const void *src, void *dest, size_t destsize,
  1139. int numinternalthreads)
  1140. {
  1141. int result;
  1142. struct blosc_context context;
  1143. context.threads_started = 0;
  1144. result = blosc_run_decompression_with_context(&context, src, dest, destsize, numinternalthreads);
  1145. if (numinternalthreads > 1)
  1146. {
  1147. blosc_release_threadpool(&context);
  1148. }
  1149. return result;
  1150. }
  1151. /* The public routine for decompression. See blosc.h for docstrings. */
  1152. int blosc_decompress(const void *src, void *dest, size_t destsize)
  1153. {
  1154. int result;
  1155. char* envvar;
  1156. long nthreads;
  1157. /* Check if should initialize */
  1158. if (!g_initlib) blosc_init();
  1159. /* Check for a BLOSC_NTHREADS environment variable */
  1160. envvar = getenv("BLOSC_NTHREADS");
  1161. if (envvar != NULL) {
  1162. nthreads = strtol(envvar, NULL, 10);
  1163. if ((nthreads != EINVAL) && (nthreads > 0)) {
  1164. result = blosc_set_nthreads((int)nthreads);
  1165. if (result < 0) { return result; }
  1166. }
  1167. }
  1168. /* Check for a BLOSC_NOLOCK environment variable. It is important
  1169. that this should be the last env var so that it can take the
  1170. previous ones into account */
  1171. envvar = getenv("BLOSC_NOLOCK");
  1172. if (envvar != NULL) {
  1173. result = blosc_decompress_ctx(src, dest, destsize, g_threads);
  1174. return result;
  1175. }
  1176. pthread_mutex_lock(&global_comp_mutex);
  1177. result = blosc_run_decompression_with_context(g_global_context, src, dest,
  1178. destsize, g_threads);
  1179. pthread_mutex_unlock(&global_comp_mutex);
  1180. return result;
  1181. }
  1182. /* Specific routine optimized for decompression a small number of
  1183. items out of a compressed chunk. This does not use threads because
  1184. it would affect negatively to performance. */
  1185. int blosc_getitem(const void *src, int start, int nitems, void *dest)
  1186. {
  1187. uint8_t *_src=NULL; /* current pos for source buffer */
  1188. uint8_t version, versionlz; /* versions for compressed header */
  1189. uint8_t flags; /* flags for header */
  1190. int32_t ntbytes = 0; /* the number of uncompressed bytes */
  1191. int32_t nblocks; /* number of total blocks in buffer */
  1192. int32_t leftover; /* extra bytes at end of buffer */
  1193. uint8_t *bstarts; /* start pointers for each block */
  1194. int tmp_init = 0;
  1195. int32_t typesize, blocksize, nbytes, ctbytes;
  1196. int32_t j, bsize, bsize2, leftoverblock;
  1197. int32_t cbytes, startb, stopb;
  1198. int stop = start + nitems;
  1199. uint8_t *tmp;
  1200. uint8_t *tmp2;
  1201. uint8_t *tmp3;
  1202. int32_t ebsize;
  1203. _src = (uint8_t *)(src);
  1204. /* Read the header block */
  1205. version = _src[0]; /* blosc format version */
  1206. versionlz = _src[1]; /* blosclz format version */
  1207. flags = _src[2]; /* flags */
  1208. typesize = (int32_t)_src[3]; /* typesize */
  1209. nbytes = sw32_(_src + 4); /* buffer size */
  1210. blocksize = sw32_(_src + 8); /* block size */
  1211. ctbytes = sw32_(_src + 12); /* compressed buffer size */
  1212. ebsize = blocksize + typesize * (int32_t)sizeof(int32_t);
  1213. tmp = my_malloc(blocksize + ebsize + blocksize);
  1214. tmp2 = tmp + blocksize;
  1215. tmp3 = tmp + blocksize + ebsize;
  1216. version += 0; /* shut up compiler warning */
  1217. versionlz += 0; /* shut up compiler warning */
  1218. ctbytes += 0; /* shut up compiler warning */
  1219. _src += 16;
  1220. bstarts = _src;
  1221. /* Compute some params */
  1222. /* Total blocks */
  1223. nblocks = nbytes / blocksize;
  1224. leftover = nbytes % blocksize;
  1225. nblocks = (leftover>0)? nblocks+1: nblocks;
  1226. _src += sizeof(int32_t)*nblocks;
  1227. /* Check region boundaries */
  1228. if ((start < 0) || (start*typesize > nbytes)) {
  1229. fprintf(stderr, "`start` out of bounds");
  1230. return -1;
  1231. }
  1232. if ((stop < 0) || (stop*typesize > nbytes)) {
  1233. fprintf(stderr, "`start`+`nitems` out of bounds");
  1234. return -1;
  1235. }
  1236. for (j = 0; j < nblocks; j++) {
  1237. bsize = blocksize;
  1238. leftoverblock = 0;
  1239. if ((j == nblocks - 1) && (leftover > 0)) {
  1240. bsize = leftover;
  1241. leftoverblock = 1;
  1242. }
  1243. /* Compute start & stop for each block */
  1244. startb = start * typesize - j * blocksize;
  1245. stopb = stop * typesize - j * blocksize;
  1246. if ((startb >= (int)blocksize) || (stopb <= 0)) {
  1247. continue;
  1248. }
  1249. if (startb < 0) {
  1250. startb = 0;
  1251. }
  1252. if (stopb > (int)blocksize) {
  1253. stopb = blocksize;
  1254. }
  1255. bsize2 = stopb - startb;
  1256. /* Do the actual data copy */
  1257. if (flags & BLOSC_MEMCPYED) {
  1258. /* We want to memcpy only */
  1259. memcpy((uint8_t *)dest + ntbytes,
  1260. (uint8_t *)src + BLOSC_MAX_OVERHEAD + j*blocksize + startb,
  1261. bsize2);
  1262. cbytes = bsize2;
  1263. }
  1264. else {
  1265. struct blosc_context context;
  1266. /* blosc_d only uses typesize and flags */
  1267. context.typesize = typesize;
  1268. context.header_flags = &flags;
  1269. /* Regular decompression. Put results in tmp2. */
  1270. cbytes = blosc_d(&context, bsize, leftoverblock,
  1271. (uint8_t *)src + sw32_(bstarts + j * 4),
  1272. tmp2, tmp, tmp3);
  1273. if (cbytes < 0) {
  1274. ntbytes = cbytes;
  1275. break;
  1276. }
  1277. /* Copy to destination */
  1278. memcpy((uint8_t *)dest + ntbytes, tmp2 + startb, bsize2);
  1279. cbytes = bsize2;
  1280. }
  1281. ntbytes += cbytes;
  1282. }
  1283. my_free(tmp);
  1284. return ntbytes;
  1285. }
  1286. /* Decompress & unshuffle several blocks in a single thread */
  1287. static void *t_blosc(void *ctxt)
  1288. {
  1289. struct thread_context* context = (struct thread_context*)ctxt;
  1290. int32_t cbytes, ntdest;
  1291. int32_t tblocks; /* number of blocks per thread */
  1292. int32_t leftover2;
  1293. int32_t tblock; /* limit block on a thread */
  1294. int32_t nblock_; /* private copy of nblock */
  1295. int32_t bsize, leftoverblock;
  1296. /* Parameters for threads */
  1297. int32_t blocksize;
  1298. int32_t ebsize;
  1299. int32_t compress;
  1300. int32_t maxbytes;
  1301. int32_t ntbytes;
  1302. int32_t flags;
  1303. int32_t nblocks;
  1304. int32_t leftover;
  1305. uint8_t *bstarts;
  1306. const uint8_t *src;
  1307. uint8_t *dest;
  1308. uint8_t *tmp;
  1309. uint8_t *tmp2;
  1310. uint8_t *tmp3;
  1311. int rc;
  1312. while(1)
  1313. {
  1314. /* Synchronization point for all threads (wait for initialization) */
  1315. WAIT_INIT(NULL, context->parent_context);
  1316. if(context->parent_context->end_threads)
  1317. {
  1318. break;
  1319. }
  1320. /* Get parameters for this thread before entering the main loop */
  1321. blocksize = context->parent_context->blocksize;
  1322. ebsize = blocksize + context->parent_context->typesize * (int32_t)sizeof(int32_t);
  1323. compress = context->parent_context->compress;
  1324. flags = *(context->parent_context->header_flags);
  1325. maxbytes = context->parent_context->destsize;
  1326. nblocks = context->parent_context->nblocks;
  1327. leftover = context->parent_context->leftover;
  1328. bstarts = context->parent_context->bstarts;
  1329. src = context->parent_context->src;
  1330. dest = context->parent_context->dest;
  1331. if (blocksize > context->tmpblocksize)
  1332. {
  1333. my_free(context->tmp);
  1334. context->tmp = my_malloc(blocksize + ebsize + blocksize);
  1335. context->tmp2 = context->tmp + blocksize;
  1336. context->tmp3 = context->tmp + blocksize + ebsize;
  1337. }
  1338. tmp = context->tmp;
  1339. tmp2 = context->tmp2;
  1340. tmp3 = context->tmp3;
  1341. ntbytes = 0; /* only useful for decompression */
  1342. if (compress && !(flags & BLOSC_MEMCPYED)) {
  1343. /* Compression always has to follow the block order */
  1344. pthread_mutex_lock(&context->parent_context->count_mutex);
  1345. context->parent_context->thread_nblock++;
  1346. nblock_ = context->parent_context->thread_nblock;
  1347. pthread_mutex_unlock(&context->parent_context->count_mutex);
  1348. tblock = nblocks;
  1349. }
  1350. else {
  1351. /* Decompression can happen using any order. We choose
  1352. sequential block order on each thread */
  1353. /* Blocks per thread */
  1354. tblocks = nblocks / context->parent_context->numthreads;
  1355. leftover2 = nblocks % context->parent_context->numthreads;
  1356. tblocks = (leftover2>0)? tblocks+1: tblocks;
  1357. nblock_ = context->tid*tblocks;
  1358. tblock = nblock_ + tblocks;
  1359. if (tblock > nblocks) {
  1360. tblock = nblocks;
  1361. }
  1362. }
  1363. /* Loop over blocks */
  1364. leftoverblock = 0;
  1365. while ((nblock_ < tblock) && context->parent_context->thread_giveup_code > 0) {
  1366. bsize = blocksize;
  1367. if (nblock_ == (nblocks - 1) && (leftover > 0)) {
  1368. bsize = leftover;
  1369. leftoverblock = 1;
  1370. }
  1371. if (compress) {
  1372. if (flags & BLOSC_MEMCPYED) {
  1373. /* We want to memcpy only */
  1374. memcpy(dest+BLOSC_MAX_OVERHEAD+nblock_*blocksize,
  1375. src+nblock_*blocksize, bsize);
  1376. cbytes = bsize;
  1377. }
  1378. else {
  1379. /* Regular compression */
  1380. cbytes = blosc_c(context->parent_context, bsize, leftoverblock, 0, ebsize,
  1381. src+nblock_*blocksize, tmp2, tmp, tmp3);
  1382. }
  1383. }
  1384. else {
  1385. if (flags & BLOSC_MEMCPYED) {
  1386. /* We want to memcpy only */
  1387. memcpy(dest+nblock_*blocksize,
  1388. src+BLOSC_MAX_OVERHEAD+nblock_*blocksize, bsize);
  1389. cbytes = bsize;
  1390. }
  1391. else {
  1392. cbytes = blosc_d(context->parent_context, bsize, leftoverblock,
  1393. src + sw32_(bstarts + nblock_ * 4),
  1394. dest+nblock_*blocksize,
  1395. tmp, tmp2);
  1396. }
  1397. }
  1398. /* Check whether current thread has to giveup */
  1399. if (context->parent_context->thread_giveup_code <= 0) {
  1400. break;
  1401. }
  1402. /* Check results for the compressed/decompressed block */
  1403. if (cbytes < 0) { /* compr/decompr failure */
  1404. /* Set giveup_code error */
  1405. pthread_mutex_lock(&context->parent_context->count_mutex);
  1406. context->parent_context->thread_giveup_code = cbytes;
  1407. pthread_mutex_unlock(&context->parent_context->count_mutex);
  1408. break;
  1409. }
  1410. if (compress && !(flags & BLOSC_MEMCPYED)) {
  1411. /* Start critical section */
  1412. pthread_mutex_lock(&context->parent_context->count_mutex);
  1413. ntdest = context->parent_context->num_output_bytes;
  1414. _sw32(bstarts + nblock_ * 4, ntdest); /* update block start counter */
  1415. if ( (cbytes == 0) || (ntdest+cbytes > maxbytes) ) {
  1416. context->parent_context->thread_giveup_code = 0; /* uncompressible buffer */
  1417. pthread_mutex_unlock(&context->parent_context->count_mutex);
  1418. break;
  1419. }
  1420. context->parent_context->thread_nblock++;
  1421. nblock_ = context->parent_context->thread_nblock;
  1422. context->parent_context->num_output_bytes += cbytes; /* update return bytes counter */
  1423. pthread_mutex_unlock(&context->parent_context->count_mutex);
  1424. /* End of critical section */
  1425. /* Copy the compressed buffer to destination */
  1426. memcpy(dest+ntdest, tmp2, cbytes);
  1427. }
  1428. else {
  1429. nblock_++;
  1430. /* Update counter for this thread */
  1431. ntbytes += cbytes;
  1432. }
  1433. } /* closes while (nblock_) */
  1434. /* Sum up all the bytes decompressed */
  1435. if ((!compress || (flags & BLOSC_MEMCPYED)) && context->parent_context->thread_giveup_code > 0) {
  1436. /* Update global counter for all threads (decompression only) */
  1437. pthread_mutex_lock(&context->parent_context->count_mutex);
  1438. context->parent_context->num_output_bytes += ntbytes;
  1439. pthread_mutex_unlock(&context->parent_context->count_mutex);
  1440. }
  1441. /* Meeting point for all threads (wait for finalization) */
  1442. WAIT_FINISH(NULL, context->parent_context);
  1443. }
  1444. /* Cleanup our working space and context */
  1445. my_free(context->tmp);
  1446. my_free(context);
  1447. return(NULL);
  1448. }
  1449. static int init_threads(struct blosc_context* context)
  1450. {
  1451. int32_t tid;
  1452. int rc2;
  1453. int32_t ebsize;
  1454. struct thread_context* thread_context;
  1455. /* Initialize mutex and condition variable objects */
  1456. pthread_mutex_init(&context->count_mutex, NULL);
  1457. /* Set context thread sentinels */
  1458. context->thread_giveup_code = 1;
  1459. context->thread_nblock = -1;
  1460. /* Barrier initialization */
  1461. #ifdef _POSIX_BARRIERS_MINE
  1462. pthread_barrier_init(&context->barr_init, NULL, context->numthreads+1);
  1463. pthread_barrier_init(&context->barr_finish, NULL, context->numthreads+1);
  1464. #else
  1465. pthread_mutex_init(&context->count_threads_mutex, NULL);
  1466. pthread_cond_init(&context->count_threads_cv, NULL);
  1467. context->count_threads = 0; /* Reset threads counter */
  1468. #endif
  1469. #if !defined(_WIN32)
  1470. /* Initialize and set thread detached attribute */
  1471. pthread_attr_init(&context->ct_attr);
  1472. pthread_attr_setdetachstate(&context->ct_attr, PTHREAD_CREATE_JOINABLE);
  1473. #endif
  1474. /* Finally, create the threads in detached state */
  1475. for (tid = 0; tid < context->numthreads; tid++) {
  1476. context->tids[tid] = tid;
  1477. /* Create a thread context thread owns context (will destroy when finished) */
  1478. thread_context = (struct thread_context*)my_malloc(sizeof(struct thread_context));
  1479. thread_context->parent_context = context;
  1480. thread_context->tid = tid;
  1481. ebsize = context->blocksize + context->typesize * (int32_t)sizeof(int32_t);
  1482. thread_context->tmp = my_malloc(context->blocksize + ebsize + context->blocksize);
  1483. thread_context->tmp2 = thread_context->tmp + context->blocksize;
  1484. thread_context->tmp3 = thread_context->tmp + context->blocksize + ebsize;
  1485. thread_context->tmpblocksize = context->blocksize;
  1486. #if !defined(_WIN32)
  1487. rc2 = pthread_create(&context->threads[tid], &context->ct_attr, t_blosc, (void *)thread_context);
  1488. #else
  1489. rc2 = pthread_create(&context->threads[tid], NULL, t_blosc, (void *)thread_context);
  1490. #endif
  1491. if (rc2) {
  1492. fprintf(stderr, "ERROR; return code from pthread_create() is %d\n", rc2);
  1493. fprintf(stderr, "\tError detail: %s\n", strerror(rc2));
  1494. return(-1);
  1495. }
  1496. }
  1497. return(0);
  1498. }
  1499. int blosc_get_nthreads(void)
  1500. {
  1501. int ret = g_threads;
  1502. return ret;
  1503. }
  1504. int blosc_set_nthreads(int nthreads_new)
  1505. {
  1506. int ret = g_threads;
  1507. /* Check if should initialize */
  1508. if (!g_initlib) blosc_init();
  1509. if (nthreads_new != ret){
  1510. /* Re-initialize Blosc */
  1511. blosc_destroy();
  1512. blosc_init();
  1513. g_threads = nthreads_new;
  1514. }
  1515. return ret;
  1516. }
  1517. int blosc_set_nthreads_(struct blosc_context* context)
  1518. {
  1519. if (context->numthreads > BLOSC_MAX_THREADS) {
  1520. fprintf(stderr,
  1521. "Error. nthreads cannot be larger than BLOSC_MAX_THREADS (%d)",
  1522. BLOSC_MAX_THREADS);
  1523. return -1;
  1524. }
  1525. else if (context->numthreads <= 0) {
  1526. fprintf(stderr, "Error. nthreads must be a positive integer");
  1527. return -1;
  1528. }
  1529. /* Launch a new pool of threads */
  1530. if (context->numthreads > 1 && context->numthreads != context->threads_started) {
  1531. blosc_release_threadpool(context);
  1532. init_threads(context);
  1533. }
  1534. /* We have now started the threads */
  1535. context->threads_started = context->numthreads;
  1536. return context->numthreads;
  1537. }
  1538. char* blosc_get_compressor(void)
  1539. {
  1540. char* compname;
  1541. blosc_compcode_to_compname(g_compressor, &compname);
  1542. return compname;
  1543. }
  1544. int blosc_set_compressor(const char *compname)
  1545. {
  1546. int code = blosc_compname_to_compcode(compname);
  1547. g_compressor = code;
  1548. /* Check if should initialize */
  1549. if (!g_initlib) blosc_init();
  1550. return code;
  1551. }
  1552. char* blosc_list_compressors(void)
  1553. {
  1554. static int compressors_list_done = 0;
  1555. static char ret[256];
  1556. if (compressors_list_done) return ret;
  1557. ret[0] = '\0';
  1558. strcat(ret, BLOSC_BLOSCLZ_COMPNAME);
  1559. #if defined(HAVE_LZ4)
  1560. strcat(ret, ","); strcat(ret, BLOSC_LZ4_COMPNAME);
  1561. strcat(ret, ","); strcat(ret, BLOSC_LZ4HC_COMPNAME);
  1562. #endif /* HAVE_LZ4 */
  1563. #if defined(HAVE_SNAPPY)
  1564. strcat(ret, ","); strcat(ret, BLOSC_SNAPPY_COMPNAME);
  1565. #endif /* HAVE_SNAPPY */
  1566. #if defined(HAVE_ZLIB)
  1567. strcat(ret, ","); strcat(ret, BLOSC_ZLIB_COMPNAME);
  1568. #endif /* HAVE_ZLIB */
  1569. compressors_list_done = 1;
  1570. return ret;
  1571. }
  1572. char* blosc_get_version_string(void)
  1573. {
  1574. static char ret[256];
  1575. strcpy(ret, BLOSC_VERSION_STRING);
  1576. return ret;
  1577. }
  1578. int blosc_get_complib_info(char *compname, char **complib, char **version)
  1579. {
  1580. int clibcode;
  1581. char *clibname;
  1582. char *clibversion = "unknown";
  1583. #if (defined(HAVE_LZ4) && defined(LZ4_VERSION_MAJOR)) || (defined(HAVE_SNAPPY) && defined(SNAPPY_VERSION))
  1584. char sbuffer[256];
  1585. #endif
  1586. clibcode = compname_to_clibcode(compname);
  1587. clibname = clibcode_to_clibname(clibcode);
  1588. /* complib version */
  1589. if (clibcode == BLOSC_BLOSCLZ_LIB) {
  1590. clibversion = BLOSCLZ_VERSION_STRING;
  1591. }
  1592. #if defined(HAVE_LZ4)
  1593. else if (clibcode == BLOSC_LZ4_LIB) {
  1594. #if defined(LZ4_VERSION_MAJOR)
  1595. sprintf(sbuffer, "%d.%d.%d",
  1596. LZ4_VERSION_MAJOR, LZ4_VERSION_MINOR, LZ4_VERSION_RELEASE);
  1597. clibversion = sbuffer;
  1598. #endif /* LZ4_VERSION_MAJOR */
  1599. }
  1600. #endif /* HAVE_LZ4 */
  1601. #if defined(HAVE_SNAPPY)
  1602. else if (clibcode == BLOSC_SNAPPY_LIB) {
  1603. #if defined(SNAPPY_VERSION)
  1604. sprintf(sbuffer, "%d.%d.%d", SNAPPY_MAJOR, SNAPPY_MINOR, SNAPPY_PATCHLEVEL);
  1605. clibversion = sbuffer;
  1606. #endif /* SNAPPY_VERSION */
  1607. }
  1608. #endif /* HAVE_SNAPPY */
  1609. #if defined(HAVE_ZLIB)
  1610. else if (clibcode == BLOSC_ZLIB_LIB) {
  1611. clibversion = ZLIB_VERSION;
  1612. }
  1613. #endif /* HAVE_ZLIB */
  1614. *complib = strdup(clibname);
  1615. *version = strdup(clibversion);
  1616. return clibcode;
  1617. }
  1618. /* Return `nbytes`, `cbytes` and `blocksize` from a compressed buffer. */
  1619. void blosc_cbuffer_sizes(const void *cbuffer, size_t *nbytes,
  1620. size_t *cbytes, size_t *blocksize)
  1621. {
  1622. uint8_t *_src = (uint8_t *)(cbuffer); /* current pos for source buffer */
  1623. uint8_t version, versionlz; /* versions for compressed header */
  1624. /* Read the version info (could be useful in the future) */
  1625. version = _src[0]; /* blosc format version */
  1626. versionlz = _src[1]; /* blosclz format version */
  1627. version += 0; /* shut up compiler warning */
  1628. versionlz += 0; /* shut up compiler warning */
  1629. /* Read the interesting values */
  1630. *nbytes = (size_t)sw32_(_src + 4); /* uncompressed buffer size */
  1631. *blocksize = (size_t)sw32_(_src + 8); /* block size */
  1632. *cbytes = (size_t)sw32_(_src + 12); /* compressed buffer size */
  1633. }
  1634. /* Return `typesize` and `flags` from a compressed buffer. */
  1635. void blosc_cbuffer_metainfo(const void *cbuffer, size_t *typesize,
  1636. int *flags)
  1637. {
  1638. uint8_t *_src = (uint8_t *)(cbuffer); /* current pos for source buffer */
  1639. uint8_t version, versionlz; /* versions for compressed header */
  1640. /* Read the version info (could be useful in the future) */
  1641. version = _src[0]; /* blosc format version */
  1642. versionlz = _src[1]; /* blosclz format version */
  1643. version += 0; /* shut up compiler warning */
  1644. versionlz += 0; /* shut up compiler warning */
  1645. /* Read the interesting values */
  1646. *flags = (int)_src[2]; /* flags */
  1647. *typesize = (size_t)_src[3]; /* typesize */
  1648. }
  1649. /* Return version information from a compressed buffer. */
  1650. void blosc_cbuffer_versions(const void *cbuffer, int *version,
  1651. int *versionlz)
  1652. {
  1653. uint8_t *_src = (uint8_t *)(cbuffer); /* current pos for source buffer */
  1654. /* Read the version info */
  1655. *version = (int)_src[0]; /* blosc format version */
  1656. *versionlz = (int)_src[1]; /* Lempel-Ziv compressor format version */
  1657. }
  1658. /* Return the compressor library/format used in a compressed buffer. */
  1659. char *blosc_cbuffer_complib(const void *cbuffer)
  1660. {
  1661. uint8_t *_src = (uint8_t *)(cbuffer); /* current pos for source buffer */
  1662. int clibcode;
  1663. char *complib;
  1664. /* Read the compressor format/library info */
  1665. clibcode = (_src[2] & 0xe0) >> 5;
  1666. complib = clibcode_to_clibname(clibcode);
  1667. return complib;
  1668. }
  1669. /* Get the internal blocksize to be used during compression. 0 means
  1670. that an automatic blocksize is computed internally. */
  1671. int blosc_get_blocksize(void)
  1672. {
  1673. return (int)g_force_blocksize;
  1674. }
  1675. /* Force the use of a specific blocksize. If 0, an automatic
  1676. blocksize will be used (the default). */
  1677. void blosc_set_blocksize(size_t size)
  1678. {
  1679. g_force_blocksize = (int32_t)size;
  1680. }
  1681. void blosc_init(void)
  1682. {
  1683. /* Return if we are already initialized */
  1684. if (g_initlib) return;
  1685. pthread_mutex_init(&global_comp_mutex, NULL);
  1686. g_global_context = (struct blosc_context*)my_malloc(sizeof(struct blosc_context));
  1687. g_global_context->threads_started = 0;
  1688. g_initlib = 1;
  1689. }
  1690. void blosc_destroy(void)
  1691. {
  1692. /* Return if Blosc is not initialized */
  1693. if (!g_initlib) return;
  1694. g_initlib = 0;
  1695. blosc_release_threadpool(g_global_context);
  1696. my_free(g_global_context);
  1697. pthread_mutex_destroy(&global_comp_mutex);
  1698. }
  1699. int blosc_release_threadpool(struct blosc_context* context)
  1700. {
  1701. int32_t t;
  1702. void* status;
  1703. int rc;
  1704. int rc2;
  1705. if (context->threads_started > 0)
  1706. {
  1707. /* Tell all existing threads to finish */
  1708. context->end_threads = 1;
  1709. /* Sync threads */
  1710. WAIT_INIT(-1, context);
  1711. /* Join exiting threads */
  1712. for (t=0; t<context->threads_started; t++) {
  1713. rc2 = pthread_join(context->threads[t], &status);
  1714. if (rc2) {
  1715. fprintf(stderr, "ERROR; return code from pthread_join() is %d\n", rc2);
  1716. fprintf(stderr, "\tError detail: %s\n", strerror(rc2));
  1717. }
  1718. }
  1719. /* Release mutex and condition variable objects */
  1720. pthread_mutex_destroy(&context->count_mutex);
  1721. /* Barriers */
  1722. #ifdef _POSIX_BARRIERS_MINE
  1723. pthread_barrier_destroy(&context->barr_init);
  1724. pthread_barrier_destroy(&context->barr_finish);
  1725. #else
  1726. pthread_mutex_destroy(&context->count_threads_mutex);
  1727. pthread_cond_destroy(&context->count_threads_cv);
  1728. #endif
  1729. /* Thread attributes */
  1730. #if !defined(_WIN32)
  1731. pthread_attr_destroy(&context->ct_attr);
  1732. #endif
  1733. }
  1734. context->threads_started = 0;
  1735. return 0;
  1736. }
  1737. int blosc_free_resources(void)
  1738. {
  1739. /* Return if Blosc is not initialized */
  1740. if (!g_initlib) return -1;
  1741. return blosc_release_threadpool(g_global_context);
  1742. }