Example #1
0
void LZ4CompressStream::FlushOut()
{
	if(ptr == (byte *)~buffer)
		return;
	
	CoWork co;
	
	int osz = LZ4_compressBound(BLOCK_BYTES);
	byte *t = ~outbuf;
	int   ii = 0;
	for(byte *s = ~buffer; s < ptr; s += BLOCK_BYTES) {
		int origsize = min((int)BLOCK_BYTES, int(ptr - s));
#ifdef _MULTITHREADED
		if(concurrent)
			co & [=] {
				outsz[ii] = LZ4_compress_default((char *)s, (char *)t, origsize, osz);
			};
		else
#endif
			outsz[ii] = LZ4_compress_default((char *)s, (char *)t, origsize, osz);
		ii++;
		t += osz;
	}
	
	if(concurrent)
		co.Finish();
	
	byte *s = ~buffer;
	t = ~outbuf;
	for(int i = 0; i < ii; i++) {
		int origsize = min((int)BLOCK_BYTES, int(ptr - s));
		int clen = outsz[i];
		if(clen < 0) {
			SetError();
			return;
		}
		if(clen >= origsize || clen == 0) {
			out->Put32le(0x80000000 | origsize);
			out->Put(s, origsize);
		}
		else {
			out->Put32le(clen);
			out->Put(t, clen);
		}
		s += BLOCK_BYTES;
		t += osz;
	}
	
	int origsize = int(ptr - ~buffer);
	xxh.Put(~buffer, origsize);
	pos += origsize;
	ptr = ~buffer;
}
	void* CBAWMeshWriter::compressWithLz4AndTryOnStack(const void* _input, size_t _inputSize, void* _stack, size_t _stackSize, size_t& _outComprSize) const
	{
		void* data = _stack;
		size_t dstSize = _stackSize;
		size_t compressedSize = 0;
		const int lz4CompressBound = LZ4_compressBound(_inputSize);

		if (lz4CompressBound) // if input is not too large
		{
			if (lz4CompressBound > _stackSize)
			{
				dstSize = asset::BlobHeaderV1::calcEncSize(lz4CompressBound);
				data = _IRR_ALIGNED_MALLOC(dstSize,_IRR_SIMD_ALIGNMENT);
			}
			compressedSize = LZ4_compress_default((const char*)_input, (char*)data, _inputSize, dstSize);
		}
		if (!compressedSize) // if compression did not succeed
		{
			if (data != _stack)
				_IRR_ALIGNED_FREE(data);
			compressedSize = _inputSize;
			data = const_cast<void*>(_input);
#ifdef _DEBUG
			os::Printer::log("Failed to compress (lz4). Blob exported without compression.", ELL_WARNING);
#endif
		}
		_outComprSize = compressedSize;
		return data;
	}
Example #3
0
File: data.c Project: 2ion/forecast
void compress_data(Data *d) {
  int slen = d->datalen;
  int olen = LZ4_COMPRESSBOUND(slen);
  char cbuf[olen];

#if LZ4_VERSION_MINOR >= 7
  int ocnt = LZ4_compress_default((const char*)d->data, cbuf, slen, olen);
#else
  /* In this API version, $cbuf is required to be large enough to handle
   * up to LZ4_COMPRESSBOUND($slen) bytes. Since we already allocate
   * this large of a buffer anyway, we just drop $olen.
   *
   * This is required for building against the liblz4 version in Debian
   * Jessie.
   */
  int ocnt = LZ4_compress((const char*)d->data, cbuf, slen);
#endif

  if(ocnt == 0) /* should never happen */
    LERROR(EXIT_FAILURE, 0, "LZ4_compress_default() failed");

  free(d->data);
  d->data = malloc(ocnt);
  GUARD_MALLOC(d->data);
  d->datalen = (size_t)ocnt;
  memcpy(d->data, (const void*)cbuf, d->datalen);
}
size_t lz4_output_stream::compress(void* sink, size_t sink_size) {
  VAST_ENTER_WITH(VAST_ARG(sink, sink_size));
  VAST_ASSERT(sink_size >= valid_bytes_);
  auto n = LZ4_compress_default(
    reinterpret_cast<char const*>(uncompressed_.data()),
    reinterpret_cast<char*>(sink),
    static_cast<int>(valid_bytes_),
    static_cast<int>(sink_size));
  VAST_ASSERT(n > 0);
  VAST_RETURN(n);
}
Example #5
0
static int __lz4_compress_crypto(const u8 *src, unsigned int slen,
				 u8 *dst, unsigned int *dlen, void *ctx)
{
	int out_len = LZ4_compress_default(src, dst,
		slen, *dlen, ctx);

	if (!out_len)
		return -EINVAL;

	*dlen = out_len;
	return 0;
}
Example #6
0
std::pair<std::unique_ptr<char[]>, size_t> compress(const void* data, size_t dataSize, int level)
{
	if (dataSize == 0) return std::make_pair(std::unique_ptr<char[]>(), 0);

	int csizeBound = LZ4_compressBound(dataSize);

	std::unique_ptr<char[]> cdata(new char[csizeBound]);
	
	int csize = (level == 0)
		? LZ4_compress_default(static_cast<const char*>(data), cdata.get(), dataSize, csizeBound)
		: LZ4_compress_HC(static_cast<const char*>(data), cdata.get(), dataSize, csizeBound, level);
	assert(csize >= 0 && csize <= csizeBound);

	return std::make_pair(std::move(cdata), csize);
}
Example #7
0
size_t LZ4Encoder::OnCode(const MemoryByteData& input, MemoryByteData& output) const
{
	MemoryStream outputStream(output);
	outputStream.Write((uint)input.Size());
	int size = LZ4_compress_default((const char*)input.Data(), (char*)output.MutableData() + sizeof(uint), (int)input.Size(), (int)output.Size() - sizeof(uint));
	if (size>0)
	{
		size += sizeof(uint);
		output.ForceSetSize(size);
	}
	else
	{
		output.ForceSetSize(0);
	}
	return size;
}
Example #8
0
int
G_lz4_compress(unsigned char *src, int src_sz, unsigned char *dst,
		int dst_sz)
{
    int err, nbytes, buf_sz;
    unsigned char *buf;

    /* Catch errors early */
    if (src == NULL || dst == NULL)
	return -1;

    /* Don't do anything if either of these are true */
    if (src_sz <= 0 || dst_sz <= 0)
	return 0;

    /* Output buffer has to be larger for single pass compression */
    buf_sz = LZ4_compressBound(src_sz);
    if (NULL == (buf = (unsigned char *)
		 G_calloc(buf_sz, sizeof(unsigned char))))
	return -1;

    /* Do single pass compression */
    err = LZ4_compress_default((char *)src, (char *)buf, src_sz, buf_sz);
    if (err <= 0) {
	G_free(buf);
	return -1;
    }
    if (err >= src_sz) {
	/* compression not possible */
	G_free(buf);
	return -2;
    }
    
    /* bytes of compressed data is return value */
    nbytes = err;

    /* Copy the data from buf to dst */
    for (err = 0; err < nbytes; err++)
	dst[err] = buf[err];

    G_free(buf);

    return nbytes;
}
Example #9
0
static mrb_value
mrb_LZ4_compress_default(mrb_state *mrb, mrb_value self)
{
  char *source;
  mrb_int source_size;

  mrb_get_args(mrb, "s", &source, &source_size);

  int maxDestSize = LZ4_COMPRESSBOUND(source_size);
  if (likely(maxDestSize)) {
    mrb_value dest = mrb_str_buf_new(mrb, maxDestSize);
    int destSize = LZ4_compress_default(source, RSTRING_PTR(dest), source_size, RSTRING_CAPA(dest));
    if (likely(destSize)) {
      return mrb_str_resize(mrb, dest, destSize);
    } else {
      mrb_raise(mrb, E_LZ4_ERROR, "cannot compress");
    }
  } else {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "source_size is too large");
  }
}
Example #10
0
lz4_log_buf* serialize_to_proto_buf_with_malloc_lz4(log_group_builder* bder)
{
    size_t length = log_get_packed_size(bder->grp);
    unsigned char * buf = (unsigned char *)malloc(length);
    log_pack(bder->grp, buf);
    int compress_bound = LZ4_compressBound(length);
    char *compress_data = (char *)malloc(compress_bound);
    int compressed_size = LZ4_compress_default((char *)buf, compress_data, length, compress_bound);
    if(compressed_size <= 0)
    {
        free(buf);
        free(compress_data);
        return NULL;
    }
    lz4_log_buf* pLogbuf = (lz4_log_buf*)malloc(sizeof(lz4_log_buf) + compressed_size);
    pLogbuf->length = compressed_size;
    pLogbuf->raw_length = length;
    memcpy(pLogbuf->data, compress_data, compressed_size);
    free(buf);
    free(compress_data);
    return pLogbuf;
}
Example #11
0
/* Write a frame or frames to the log. */
int sqlite3WalFrames(Wal *pWal, int szPage, PgHdr *pList, Pgno nTruncate, int isCommit, int sync_flags)
{
	PgHdr *p;
	MDB_val key, data;
	int rc;
	mdbinf* mdb;
	MDB_txn* txn;
	#if ATOMIC
	db_thread *thr      = g_tsd_thread;
	db_connection* pCon	= g_tsd_conn;
	#else
	db_thread* thr = enif_tsd_get(g_tsd_thread);
	db_connection* pCon = enif_tsd_get(g_tsd_conn);
	#endif

	#if ATOMIC
	if (!g_tsd_wmdb)
		lock_wtxn(thr->nEnv);
	mdb = g_tsd_wmdb;
	#else
	mdb = enif_tsd_get(g_tsd_wmdb);
	if (!mdb)
		lock_wtxn(thr->nEnv);
	mdb = enif_tsd_get(g_tsd_wmdb);
	#endif
	txn = mdb->txn;

	if (!mdb)
		return SQLITE_ERROR;

	key.mv_size = sizeof(u64);
	key.mv_data = (void*)&pWal->index;

	// Term/evnum must always be increasing
	if ((pWal->inProgressTerm > 0 && pWal->inProgressTerm < pWal->lastCompleteTerm) ||
		(pWal->inProgressEvnum > 0 && pWal->inProgressEvnum < pWal->lastCompleteEvnum))
		return SQLITE_ERROR;

	track_time(2,thr);
	// ** - Pages DB: {<<ActorIndex:64, Pgno:32/unsigned>>, <<Evterm:64,Evnum:64,Fragment,CompressedPage/binary>>}
	for(p=pList; p; p=p->pDirty)
	{
		u8 pagesKeyBuf[sizeof(u64)+sizeof(u32)];
		u8 pagesBuf[PAGE_BUFF_SIZE];
		int full_size = 0;
		int page_size = LZ4_compress_default((char*)p->pData,(char*)pagesBuf+sizeof(u64)*2+1,szPage,sizeof(pagesBuf));
		char fragment_index = 0;
		int skipped = 0;
		track_time(3,thr);

		DBG("Insert frame, actor=%lld, pgno=%u, "
			"term=%lld, evnum=%lld, commit=%d, truncate=%d, compressedsize=%d",
		pWal->index,p->pgno,pWal->inProgressTerm,pWal->inProgressEvnum,
		isCommit,nTruncate,page_size);

		if (pCon->doReplicate)
		{
			u8 hdr[sizeof(u64)*2+sizeof(u32)*2];
			put8byte(hdr,               pWal->inProgressTerm);
			put8byte(hdr+sizeof(u64),   pWal->inProgressEvnum);
			put4byte(hdr+sizeof(u64)*2, p->pgno);
			if (p->pDirty)
				put4byte(hdr+sizeof(u64)*2+sizeof(u32), 0);
			else
				put4byte(hdr+sizeof(u64)*2+sizeof(u32), nTruncate);
			#ifndef _TESTAPP_
			wal_page_hook(thr,pagesBuf+sizeof(u64)*2+1, page_size, hdr, sizeof(hdr));
			#endif
		}

		memcpy(pagesKeyBuf,               &pWal->index,sizeof(u64));
		memcpy(pagesKeyBuf + sizeof(u64), &p->pgno,    sizeof(u32));
		key.mv_size = sizeof(pagesKeyBuf);
		key.mv_data = pagesKeyBuf;
		

		// Check if there are pages with the same or higher evnum/evterm. If there are, delete them.
		// This can happen if sqlite flushed some page to disk before commiting, because there were
		// so many pages that they could not be held in memory. Or it could happen if pages need to be
		// overwritten because there was a write that did not pass raft consensus.
		rc = mdb_cursor_get(mdb->cursorPages,&key,&data,MDB_SET_KEY);
		if (rc == MDB_SUCCESS)
		{
			size_t ndupl;
			mdb_cursor_count(mdb->cursorPages,&ndupl);

			rc = mdb_cursor_get(mdb->cursorPages,&key,&data,MDB_LAST_DUP);
			if (rc == MDB_SUCCESS)
			{
				MDB_val pgDelKey = {0,NULL}, pgDelVal = {0,NULL};
				u64 evnum, evterm;
				u8 frag = *((u8*)data.mv_data+sizeof(u64)*2);
				memcpy(&evterm, data.mv_data,               sizeof(u64));
				memcpy(&evnum,  (u8*)data.mv_data + sizeof(u64), sizeof(u64));

				while ((evterm > pWal->inProgressTerm || evnum >= pWal->inProgressEvnum))
						//(pWal->inProgressTerm + pWal->inProgressEvnum) > 0)
				{
					DBG("Deleting pages higher or equal to current. "
					"Evterm=%llu, evnum=%llu, curterm=%llu, curevn=%llu, dupl=%ld",
					evterm,evnum,pWal->inProgressTerm,pWal->inProgressEvnum,ndupl);

					if (pgDelKey.mv_data != NULL)
					{
						if ((rc = mdb_del(txn,mdb->pagesdb,&pgDelKey,&pgDelVal)) != MDB_SUCCESS)
						{
							DBG("Unable to cleanup page from pagedb %d",rc);
							break;
						}
						pgDelKey.mv_data = NULL;
					}
					mdb_cursor_get(mdb->cursorPages,&pgDelKey,&pgDelVal,MDB_GET_CURRENT);

					// if (mdb_cursor_del(mdb->cursorPages,0) != MDB_SUCCESS)
					// {
					// 	DBG("Cant delete!");
					// 	break;
					// }

					if (frag == 0)
						pWal->allPages--;
					ndupl--;
					if (!ndupl)
						break;
					rc = mdb_cursor_get(mdb->cursorPages,&key,&data,MDB_PREV_DUP);
					if (rc != MDB_SUCCESS)
						break;
					memcpy(&evterm, data.mv_data,               sizeof(u64));
					memcpy(&evnum,  (u8*)data.mv_data + sizeof(u64), sizeof(u64));
					frag = *((u8*)data.mv_data+sizeof(u64)*2);
				}
				if (pgDelKey.mv_data != NULL)
				{
					if ((rc = mdb_del(txn,mdb->pagesdb,&pgDelKey,&pgDelVal)) != MDB_SUCCESS)
					{
						DBG("Unable to cleanup page from pagedb %d",rc);
						break;
					}
					pgDelKey.mv_data = NULL;
				}
			}
			memcpy(pagesKeyBuf,               &pWal->index,sizeof(u64));
			memcpy(pagesKeyBuf + sizeof(u64), &p->pgno,    sizeof(u32));
			key.mv_size = sizeof(pagesKeyBuf);
			key.mv_data = pagesKeyBuf;
		}
		track_time(4,thr);

		memcpy(pagesBuf,               &pWal->inProgressTerm,  sizeof(u64));
		memcpy(pagesBuf + sizeof(u64), &pWal->inProgressEvnum, sizeof(u64));

		full_size = page_size + sizeof(u64)*2 + 1;
		if (full_size < thr->maxvalsize)
			fragment_index = 0;
		else
		{
			full_size = page_size;
			skipped = thr->maxvalsize - sizeof(u64)*2 - 1;
			full_size -= skipped;
			while(full_size > 0)
			{
				full_size -= (thr->maxvalsize - sizeof(u64)*2 - 1);
				fragment_index++;
			}
			full_size = page_size + sizeof(u64)*2 +1;
		}

		pagesBuf[sizeof(u64)*2] = fragment_index;
		data.mv_size = fragment_index == 0 ? full_size : thr->maxvalsize;
		data.mv_data = pagesBuf;

		// fragment_index == 0 ? MDB_APPENDDUP : 0
		if ((rc = mdb_cursor_put(mdb->cursorPages,&key,&data,0)) != MDB_SUCCESS)
		{
			// printf("Cursor put failed to pages %d",rc);
			DBG("ERROR: cursor put failed=%d, datasize=%d",rc,full_size);
			return SQLITE_ERROR;
		}

		fragment_index--;
		skipped = data.mv_size;
		while (fragment_index >= 0)
		{
			DBG("Insert fragment %d",(int)fragment_index);
			if (fragment_index == 0)
				data.mv_size = full_size - skipped + sizeof(u64)*2 + 1;
			else
				data.mv_size = thr->maxvalsize;
			data.mv_data = pagesBuf + skipped - (sizeof(u64)*2+1);
			memcpy(pagesBuf + skipped - (sizeof(u64)*2+1), &pWal->inProgressTerm,  sizeof(u64));
			memcpy(pagesBuf + skipped - (sizeof(u64)+1),   &pWal->inProgressEvnum, sizeof(u64));
			pagesBuf[skipped-1] = fragment_index;

			if ((rc = mdb_cursor_put(mdb->cursorPages,&key,&data,0)) != MDB_SUCCESS)
			{
				DBG("ERROR: cursor secondary put failed: err=%d, datasize=%d, skipped=%d, frag=%d",
				rc,full_size, skipped, (int)fragment_index);
				return SQLITE_ERROR;
			}
			skipped += data.mv_size - sizeof(u64)*2 - 1;
			fragment_index--;
		}

		thr->pagesChanged++;
	}
	// printf("");
	// ** - Log DB: {<<ActorIndex:64, Evterm:64, Evnum:64>>, <<Pgno:32/unsigned>>}
	if (pWal->inProgressTerm > 0)
	{
		for(p=pList; p; p=p->pDirty)
		{
			u8 logKeyBuf[sizeof(u64)*3];

			DBG("Inserting to log");

			memcpy(logKeyBuf,                 &pWal->index,           sizeof(u64));
			memcpy(logKeyBuf + sizeof(u64),   &pWal->inProgressTerm,  sizeof(u64));
			memcpy(logKeyBuf + sizeof(u64)*2, &pWal->inProgressEvnum, sizeof(u64));
			key.mv_size = sizeof(logKeyBuf);
			key.mv_data = logKeyBuf;

			data.mv_size = sizeof(u32);
			data.mv_data = &p->pgno;

			if (mdb_cursor_put(mdb->cursorLog,&key,&data,0) != MDB_SUCCESS)
			{
				// printf("Cursor put failed to log");
				DBG("ERROR: cursor put to log failed: %d",rc);
				return SQLITE_ERROR;
			}

			pWal->allPages++;
		}
	}
	else
	{
		DBG("Skipping log");
		for(p=pList; p; p=p->pDirty)
			pWal->allPages++;
	}
  /** - Info DB: {<<ActorIndex:64>>, <<V,FirstCompleteTerm:64,FirstCompleteEvnum:64,
										LastCompleteTerm:64,LastCompleteEvnum:64,
										InprogressTerm:64,InProgressEvnum:64>>} */
	{
		if (isCommit)
		{
			DBG("Commit actor=%llu fct=%llu, fcev=%llu, lct=%llu, lcev=%llu, int=%llu, inev=%llu",
				pWal->index,
				pWal->firstCompleteTerm, pWal->firstCompleteEvnum, pWal->lastCompleteTerm,
				pWal->lastCompleteEvnum, pWal->inProgressTerm,pWal->inProgressEvnum);

			#ifndef _TESTAPP_
			enif_mutex_lock(pWal->mtx);
			#endif
			pWal->lastCompleteTerm = pWal->inProgressTerm > 0 ? 
				pWal->inProgressTerm : pWal->lastCompleteTerm;
			pWal->lastCompleteEvnum = pWal->inProgressEvnum > 0 ? 
				pWal->inProgressEvnum : pWal->lastCompleteEvnum;
			if (pWal->firstCompleteTerm == 0)
			{
				pWal->firstCompleteTerm = pWal->inProgressTerm;
				pWal->firstCompleteEvnum = pWal->inProgressEvnum;
			}
			pWal->inProgressTerm = pWal->inProgressEvnum = 0;
			pWal->mxPage =  pWal->mxPage > nTruncate ? pWal->mxPage : nTruncate;
			// pWal->changed = 0;
			thr->forceCommit = 1;
			pCon->dirty = 0;
			#ifndef _TESTAPP_
			enif_mutex_unlock(pWal->mtx);
			#endif
			DBG("cur mxpage=%u",pWal->mxPage);
		}
		else
		{
			// pWal->changed = 1;
			pCon->dirty = 1;
		}
		thr->pagesChanged++;

		rc = storeinfo(pWal,0,0,NULL);
		if (rc != SQLITE_OK)
			return rc;

		track_time(5,thr);
	}

	return SQLITE_OK;
}
Example #12
0
void store_cb (flux_t *h, flux_msg_handler_t *mh,
               const flux_msg_t *msg, void *arg)
{
    sqlite_ctx_t *ctx = arg;
    const void *data;
    int size, hash_len;
    uint8_t hash[BLOBREF_MAX_DIGEST_SIZE];
    char blobref[BLOBREF_MAX_STRING_SIZE] = "-";
    int uncompressed_size = -1;
    int rc = -1;
    int old_state;
    //delay cancellation to ensure lock-correctness in sqlite
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);

    if (flux_request_decode_raw (msg, NULL, &data, &size) < 0) {
        flux_log_error (h, "store: request decode failed");
        goto done;
    }
    if (size > ctx->blob_size_limit) {
        errno = EFBIG;
        goto done;
    }
    if (blobref_hash (ctx->hashfun, (uint8_t *)data, size, blobref,
                      sizeof (blobref)) < 0)
        goto done;
    if ((hash_len = blobref_strtohash (blobref, hash, sizeof (hash))) < 0)
        goto done;
    if (size >= compression_threshold) {
        int r;
        int out_len = LZ4_compressBound(size);
        if (ctx->lzo_bufsize < out_len && grow_lzo_buf (ctx, out_len) < 0)
            goto done;
        r = LZ4_compress_default (data, ctx->lzo_buf, size, out_len);
        if (r == 0) {
            errno = EINVAL;
            goto done;
        }
        uncompressed_size = size;
        size = r;
        data = ctx->lzo_buf;
    }
    if (sqlite3_bind_text (ctx->store_stmt, 1, (char *)hash, hash_len,
                           SQLITE_STATIC) != SQLITE_OK) {
        log_sqlite_error (ctx, "store: binding key");
        set_errno_from_sqlite_error (ctx);
        goto done;
    }
    if (sqlite3_bind_int (ctx->store_stmt, 2, uncompressed_size) != SQLITE_OK) {
        log_sqlite_error (ctx, "store: binding size");
        set_errno_from_sqlite_error (ctx);
        goto done;
    }
    if (sqlite3_bind_blob (ctx->store_stmt, 3,
                           data, size, SQLITE_STATIC) != SQLITE_OK) {
        log_sqlite_error (ctx, "store: binding data");
        set_errno_from_sqlite_error (ctx);
        goto done;
    }
    if (sqlite3_step (ctx->store_stmt) != SQLITE_DONE
                    && sqlite3_errcode (ctx->db) != SQLITE_CONSTRAINT) {
        log_sqlite_error (ctx, "store: executing stmt");
        set_errno_from_sqlite_error (ctx);
        goto done;
    }
    rc = 0;
done:
    if (rc < 0) {
        if (flux_respond_error (h, msg, errno, NULL) < 0)
            flux_log_error (h, "store: flux_respond_error");
    }
    else {
        if (flux_respond_raw (h, msg, blobref, strlen (blobref) + 1) < 0)
            flux_log_error (h, "store: flux_respond_raw");
    }
    (void) sqlite3_reset (ctx->store_stmt);
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state);
}
Example #13
0
static ZEND_FUNCTION(lz4_compress)
{
    zval *data;
    char *output;
    int output_len, data_len, dst_len;
    long level = 0;
    long maxLevel = (long)PHP_LZ4_CLEVEL_MAX;
    char *extra = NULL;
#if ZEND_MODULE_API_NO >= 20141001
    size_t extra_len = -1;
#else
    int extra_len = -1;
#endif
    int offset = 0;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
                              "z|ls", &data, &level,
                              &extra, &extra_len) == FAILURE) {
        RETURN_FALSE;
    }

    if (Z_TYPE_P(data) != IS_STRING) {
        zend_error(E_WARNING,
                   "lz4_compress : expects parameter to be string.");
        RETURN_FALSE;
    }

    if (extra && extra_len > 0) {
        offset = extra_len;
    } else {
        offset = sizeof(int);
    }

    data_len = Z_STRLEN_P(data);
    dst_len = LZ4_compressBound(data_len) + offset;

    output = (char *)emalloc(dst_len);
    if (!output) {
        zend_error(E_WARNING, "lz4_compress : memory error");
        RETURN_FALSE;
    }

    if (extra && extra_len > 0) {
        memcpy(output, extra, offset);
    } else {
        /* Set the data length */
        memcpy(output, &data_len, offset);
    }

    if (level == 0) {
        output_len = LZ4_compress_default(Z_STRVAL_P(data), output + offset, data_len, dst_len - offset - 1);
    } else {
        if (level > maxLevel || level < 0) {
            zend_error(E_WARNING, "lz4_compress: compression level (%ld)"
                       " must be within 1..%ld", level, maxLevel);
            efree(output);
            RETURN_FALSE;
        }
        output_len = LZ4_compress_HC(Z_STRVAL_P(data), output + offset, data_len, dst_len - offset - 1, level);
    }

    if (output_len <= 0) {
        RETVAL_FALSE;
    } else {
#if ZEND_MODULE_API_NO >= 20141001
        RETVAL_STRINGL(output, output_len + offset);
#else
        RETVAL_STRINGL(output, output_len + offset, 1);
#endif
    }

    efree(output);
}
Example #14
0
void CompressedWriteBuffer::nextImpl()
{
    if (!offset())
        return;

    size_t uncompressed_size = offset();
    size_t compressed_size = 0;
    char * compressed_buffer_ptr = nullptr;

    /** The format of compressed block - see CompressedStream.h
      */

    switch (method)
    {
        case CompressionMethod::LZ4:
        case CompressionMethod::LZ4HC:
        {
            static constexpr size_t header_size = 1 + sizeof(UInt32) + sizeof(UInt32);

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
            compressed_buffer.resize(header_size + LZ4_COMPRESSBOUND(uncompressed_size));
#pragma GCC diagnostic pop

            compressed_buffer[0] = static_cast<UInt8>(CompressionMethodByte::LZ4);

            if (method == CompressionMethod::LZ4)
                compressed_size = header_size + LZ4_compress_default(
                    working_buffer.begin(),
                    &compressed_buffer[header_size],
                    uncompressed_size,
                    LZ4_COMPRESSBOUND(uncompressed_size));
            else
                compressed_size = header_size + LZ4_compress_HC(
                    working_buffer.begin(),
                    &compressed_buffer[header_size],
                    uncompressed_size,
                    LZ4_COMPRESSBOUND(uncompressed_size),
                    0);

            UInt32 compressed_size_32 = compressed_size;
            UInt32 uncompressed_size_32 = uncompressed_size;

            unalignedStore(&compressed_buffer[1], compressed_size_32);
            unalignedStore(&compressed_buffer[5], uncompressed_size_32);

            compressed_buffer_ptr = &compressed_buffer[0];
            break;
        }
        case CompressionMethod::ZSTD:
        {
            static constexpr size_t header_size = 1 + sizeof(UInt32) + sizeof(UInt32);

            compressed_buffer.resize(header_size + ZSTD_compressBound(uncompressed_size));

            compressed_buffer[0] = static_cast<UInt8>(CompressionMethodByte::ZSTD);

            size_t res = ZSTD_compress(
                &compressed_buffer[header_size],
                compressed_buffer.size(),
                working_buffer.begin(),
                uncompressed_size,
                1);

            if (ZSTD_isError(res))
                throw Exception("Cannot compress block with ZSTD: " + std::string(ZSTD_getErrorName(res)), ErrorCodes::CANNOT_COMPRESS);

            compressed_size = header_size + res;

            UInt32 compressed_size_32 = compressed_size;
            UInt32 uncompressed_size_32 = uncompressed_size;

            unalignedStore(&compressed_buffer[1], compressed_size_32);
            unalignedStore(&compressed_buffer[5], uncompressed_size_32);

            compressed_buffer_ptr = &compressed_buffer[0];
            break;
        }
        default:
            throw Exception("Unknown compression method", ErrorCodes::UNKNOWN_COMPRESSION_METHOD);
    }

    CityHash_v1_0_2::uint128 checksum = CityHash_v1_0_2::CityHash128(compressed_buffer_ptr, compressed_size);
    out.write(reinterpret_cast<const char *>(&checksum), sizeof(checksum));

    out.write(compressed_buffer_ptr, compressed_size);
}
Example #15
0
size_t compress(const char* in, size_t in_size, char* out, size_t out_size) {
  return LZ4_compress_default(in, out, in_size, out_size);
}
static int ct_archive_data(struct hsm_copyaction_private *hcp, const char *src,
                           const char *dst, int src_fd,
                           const struct hsm_action_item *hai, long hal_flags)
{
    struct hsm_extent he;
    __u64             file_offset = hai->hai_extent.offset;
    struct stat       src_st;
    char              *uncompress_buf = NULL;
    char              *compress_buf = NULL;
    __u64             write_total = 0;
    __u64             length = hai->hai_extent.length;
    time_t            last_report_time;
    int               rc = 0;
    double            start_ct_now = ct_now();
    time_t            now;
    int               compression_bound = LZ4_compressBound(chunk_size);

    // Archiving a file from Lustre to the object store
    CT_TRACE("Archiving %s to %s", src, dst);
    if (fstat(src_fd, &src_st) < 0) {
        rc = -errno;
        CT_ERROR(rc, "cannot stat '%s'", src);
        return rc;
    }

    if (!S_ISREG(src_st.st_mode)) {
        rc = -EINVAL;
        CT_ERROR(rc, "'%s' is not a regular file", src);
        return rc;
    }

    if (hai->hai_extent.offset > (__u64)src_st.st_size) {
        rc = -EINVAL;
        CT_ERROR(rc, "Trying to start reading past end ("LPU64" > "
                 "%jd) of '%s' source file", hai->hai_extent.offset,
                 (intmax_t)src_st.st_size, src);
        return rc;
    }

    strippingInfo stripping_params;
    stripping_params.lmm_stripe_count = 1;
    stripping_params.lmm_stripe_size = ONE_MB;

    if (ct_save_stripe(src_fd, src, &stripping_params)) {
        return -1;
    }

    /* Don't read beyond a given extent */
    if (length > src_st.st_size - hai->hai_extent.offset)
        length = src_st.st_size - hai->hai_extent.offset;

    last_report_time = time(NULL);

    he.offset = file_offset;
    he.length = 0;
    rc = llapi_hsm_action_progress(hcp, &he, length, 0);
    if (rc < 0) {
        /* Action has been canceled or something wrong
         * is happening. Stop copying data. */
        CT_ERROR(rc, "progress ioctl for copy '%s'->'%s' failed",
                 src, dst);
        goto out;
    }

    errno = 0;

    uncompress_buf = malloc(chunk_size);
    if (uncompress_buf == NULL) {
        rc = -ENOMEM;
        goto out;
    }

    compress_buf = malloc(compression_bound);
    if (compress_buf == NULL) {
        rc = -ENOMEM;
        goto out;
    }

    int chunk_id = -1;

    const char totalLength[] = "totallength";
    const char chunksize[] = "chunksize";
    const char stripe_size[] = "stripesize";
    const char stripe_count[] = "stripecount";
    const char path[] = "path";
    const char uid[] = "uid";
    const char gid[] = "gid";

    char totalLength_s[TOTALLENGTH];
    char chunksize_s[TOTALLENGTH];
    char stripe_size_s[TOTALLENGTH];
    char stripe_count_s[TOTALLENGTH];
    char path_s[PATH_MAX];
    char uid_s[TOTALLENGTH];
    char gid_s[TOTALLENGTH];

    snprintf(totalLength_s, sizeof(totalLength_s), "%llu", length);
    snprintf(chunksize_s, sizeof(chunksize_s), "%i", chunk_size);
    snprintf(stripe_size_s, sizeof(stripe_size_s), "%i", stripping_params.lmm_stripe_size);
    snprintf(stripe_count_s, sizeof(stripe_count_s), "%i", stripping_params.lmm_stripe_count);
    snprintf(path_s, sizeof(path_s), "%s", src); // FIXME should use fid2path to get the normal path
    snprintf(uid_s, sizeof(uid_s), "%i", src_st.st_uid);
    snprintf(gid_s, sizeof(gid_s), "%i", src_st.st_gid);

    // Saving some metadata for disaster recovery
    S3NameValue metadata[7] =
    {
        {
            totalLength,
            totalLength_s,
        },
        {
            chunksize,
            chunksize_s,
        },
        {
            stripe_size,
            stripe_size_s,
        },
        {
            stripe_count,
            stripe_count_s,
        },
        {
            path,
            path_s
        },
        {
            uid,
            uid_s
        },
        {
            gid,
            gid_s
        }
    };

    S3PutProperties putProperties =
    {
        // application/x-lz4 does not officially exist
        "application/x-lz4", // contentType
        NULL, // md5
        NULL, // cacheControl
        NULL, // contentDispositionFilename
        NULL, // contentEncoding
        -1, // expires
        0, // cannedAcl
        sizeof(metadata) / sizeof(S3NameValue), // metaDataCount
        metadata, // S3NameValue *metaData
        0, // useServerSideEncryption
    };

    do {
        // Uploading to object store

        if (chunk_id == -1) {
            CT_TRACE("start copy of "LPU64" bytes from '%s' to '%s'",
                     length, src, dst);
        }

        // size of the current chunk, limited by chunk_size
        long long unsigned int  chunk;

        if (length - write_total > chunk_size) {
            // upper bound is the chunk_size
            chunk = chunk_size;
        }
        else {
            // limited by the file
            chunk = length - write_total;
        }

        chunk_id = file_offset / chunk_size;

        put_object_callback_data data;

        data.buffer_offset = 0;
        double before_lustre_read = ct_now();
        pread(src_fd, uncompress_buf, chunk, file_offset);
        CT_TRACE("Reading a chunk from %s of %llu bytes offset %llu from lustre took %fs",
            src, chunk, file_offset, ct_now() - before_lustre_read);

        double before_compression = ct_now();
        int compressed_size = LZ4_compress_default(uncompress_buf, compress_buf, chunk, compression_bound);
        CT_TRACE("Compressing a chunk from %s took %fs and the compressed size is %i bytes",
            src,  ct_now() - before_compression, compressed_size);

        if (compressed_size <= 0) {
            rc = -1;
            CT_ERROR(rc, "Compression error");
            goto out;
        }
        data.contentLength = compressed_size;
        data.buffer = compress_buf;

        S3PutObjectHandler putObjectHandler =
        {
            putResponseHandler,
            &putObjectDataCallback
        };

        char dst_chunk_s[S3_MAX_KEY_SIZE];
        snprintf(dst_chunk_s, sizeof(dst_chunk_s), "%s.%i", dst, chunk_id);

        char bucket_name[S3_MAX_BUCKET_NAME_SIZE];
        getBucketName(sizeof(bucket_name), bucket_name, dst_chunk_s);

        // Get a local copy of the general bucketContext than overwrite the
        // pointer to the bucket_name
        S3BucketContext localbucketContext;
        memcpy(&localbucketContext, &bucketContext, sizeof(S3BucketContext));
        localbucketContext.bucketName = bucket_name;

        double before_s3_put = ct_now();
        int retry_count = RETRYCOUNT;
        do {
            S3_put_object(&localbucketContext, dst_chunk_s, compressed_size, &putProperties, NULL, &putObjectHandler, &data);
        } while (S3_status_is_retryable(data.status) && should_retry(&retry_count));
        CT_TRACE("S3 put of %s took %fs",
            dst_chunk_s, ct_now() - before_s3_put);

        if (data.status != S3StatusOK) {
            rc = -EIO;
            CT_ERROR(rc, "S3Error %s", S3_get_status_name(data.status));
            goto out;
        }

        he.offset = file_offset;
        he.length = chunk;

        now = time(NULL);
        if (now >= last_report_time + ct_opt.o_report_int) {
            last_report_time = now;
            CT_TRACE("sending progress report for archiving %s", src);
            rc = llapi_hsm_action_progress(hcp, &he, length, 0);
            if (rc < 0) {
                /* Action has been canceled or something wrong
                 * is happening. Stop copying data. */
                CT_ERROR(rc, "progress ioctl for copy '%s'->'%s' failed",
                         src, dst);
                goto out;
            }
        }

        write_total += chunk;
        file_offset += chunk;
    } while (file_offset < length);
    rc = 0;

    // We need to delete every chunk of higher chunk_id if they
    // exists, this can happen if the new file is smaller
    // TODO only delete objects if this is a dirty write

    chunk_id += 1;
    do {
        char dst_s[S3_MAX_KEY_SIZE];
        int retry_count;

        snprintf(dst_s, sizeof(dst_s), "%s.%i", dst, chunk_id);
        get_object_callback_data head_data;
        get_object_callback_data delete_data;

        char bucket_name[S3_MAX_BUCKET_NAME_SIZE];
        getBucketName(sizeof(bucket_name), bucket_name, dst_s);

        // Get a local copy of the general bucketContext than overwrite the
        // pointer to the bucket_name
        S3BucketContext localbucketContext;
        memcpy(&localbucketContext, &bucketContext, sizeof(S3BucketContext));
        localbucketContext.bucketName = bucket_name;

        CT_TRACE("Checking if chunk %i exists", chunk_id);
        retry_count = RETRYCOUNT;
        do {
            S3_head_object(&localbucketContext, dst_s, NULL, &headResponseHandler, &head_data);
        } while (S3_status_is_retryable(head_data.status) && should_retry(&retry_count));

        if (head_data.status == S3StatusHttpErrorNotFound) {
            // Object do not exist, this mean we stop deleting chunks
            CT_TRACE("Chunk %i do not exists", chunk_id);
            break;
        }

        if (head_data.status != S3StatusOK) {
            rc = -EIO;
            CT_ERROR(rc, "S3Error %s", S3_get_status_name(head_data.status));
            goto out;
        }

        CT_TRACE("Deleting chunk %i", chunk_id);
        retry_count = RETRYCOUNT;
        do {
            S3_delete_object(&localbucketContext, dst_s, NULL, &deleteResponseHandler, &delete_data);
        } while (S3_status_is_retryable(delete_data.status) && should_retry(&retry_count));

        if (delete_data.status != S3StatusOK) {
            rc = -EIO;
            CT_ERROR(rc, "S3Error %s", S3_get_status_name(delete_data.status));
            goto out;
        }

        chunk_id++;
    } while (true);

out:
    if (uncompress_buf != NULL)
        free(uncompress_buf);
    if (compress_buf != NULL)
        free(compress_buf);

    CT_TRACE("copied "LPU64" bytes in %f seconds",
             length, ct_now() - start_ct_now);

    return rc;
}
Example #17
0
int64_t lzbench_lz4_compress(char *inbuf, size_t insize, char *outbuf, size_t outsize, size_t level, size_t, char*)
{
	return LZ4_compress_default(inbuf, outbuf, insize, outsize);
}
Example #18
0
/*
 * main
 */
int main(void) {
  /* Introduction */
  // Below we will have a Compression and Decompression section to demonstrate.
  // There are a few important notes before we start:
  //   1) The return codes of LZ4_ functions are important.
  //      Read lz4.h if you're unsure what a given code means.
  //   2) LZ4 uses char* pointers in all LZ4_ functions.
  //      This is baked into the API and probably not going to change.
  //      If your program uses pointers that are unsigned char*, void*, or otherwise different,
  //      you may need to do some casting or set the right -W compiler flags to ignore those warnings (e.g.: -Wno-pointer-sign).

  /* Compression */
  // We'll store some text into a variable pointed to by *src to be compressed later.
  const char* const src = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
  // The compression function needs to know how many bytes exist.  Since we're using a string, we can use strlen() + 1 (for \0).
  const int src_size = (int)(strlen(src) + 1);
  // LZ4 provides a function that will tell you the maximum size of compressed output based on input data via LZ4_compressBound().
  const int max_dst_size = LZ4_compressBound(src_size);
  // We will use that size for our destination boundary when allocating space.
  char* compressed_data = malloc(max_dst_size);
  if (compressed_data == NULL)
    run_screaming("Failed to allocate memory for *compressed_data.", 1);
  // That's all the information and preparation LZ4 needs to compress *src into *compressed_data.
  // Invoke LZ4_compress_default now with our size values and pointers to our memory locations.
  // Save the return value for error checking.
  const int compressed_data_size = LZ4_compress_default(src, compressed_data, src_size, max_dst_size);
  // Check return_value to determine what happened.
  if (compressed_data_size < 0)
    run_screaming("A negative result from LZ4_compress_default indicates a failure trying to compress the data.  See exit code (echo $?) for value returned.", compressed_data_size);
  if (compressed_data_size == 0)
    run_screaming("A result of 0 means compression worked, but was stopped because the destination buffer couldn't hold all the information.", 1);
  if (compressed_data_size > 0)
    printf("We successfully compressed some data!\n");
  // Not only does a positive return_value mean success, the value returned == the number of bytes required.
  // You can use this to realloc() *compress_data to free up memory, if desired.  We'll do so just to demonstrate the concept.
  compressed_data = (char *)realloc(compressed_data, compressed_data_size);
  if (compressed_data == NULL)
    run_screaming("Failed to re-alloc memory for compressed_data.  Sad :(", 1);

  /* Decompression */
  // Now that we've successfully compressed the information from *src to *compressed_data, let's do the opposite!  We'll create a
  // *new_src location of size src_size since we know that value.
  char* const regen_buffer = malloc(src_size);
  if (regen_buffer == NULL)
    run_screaming("Failed to allocate memory for *regen_buffer.", 1);
  // The LZ4_decompress_safe function needs to know where the compressed data is, how many bytes long it is,
  // where the regen_buffer memory location is, and how large regen_buffer (uncompressed) output will be.
  // Again, save the return_value.
  const int decompressed_size = LZ4_decompress_safe(compressed_data, regen_buffer, compressed_data_size, src_size);
  free(compressed_data);   /* no longer useful */
  if (decompressed_size < 0)
    run_screaming("A negative result from LZ4_decompress_safe indicates a failure trying to decompress the data.  See exit code (echo $?) for value returned.", decompressed_size);
  if (decompressed_size == 0)
    run_screaming("I'm not sure this function can ever return 0.  Documentation in lz4.h doesn't indicate so.", 1);
  if (decompressed_size > 0)
    printf("We successfully decompressed some data!\n");
  // Not only does a positive return value mean success,
  // value returned == number of bytes regenerated from compressed_data stream.

  /* Validation */
  // We should be able to compare our original *src with our *new_src and be byte-for-byte identical.
  if (memcmp(src, regen_buffer, src_size) != 0)
    run_screaming("Validation failed.  *src and *new_src are not identical.", 1);
  printf("Validation done.  The string we ended up with is:\n%s\n", regen_buffer);
  return 0;
}