libnxz / power-gzip

POWER NX zlib compliant library
23 stars 18 forks source link

Nxgzip testing failed by Java application testing #202

Open chenhealth1234 opened 1 year ago

chenhealth1234 commented 1 year ago

the issue is as follow: LD_PRELOAD=/root/fj/power-gzip-0.63/lib/.libs/libnxz.so java InflateIn_DeflateOut

java.lang.InternalError: unknown error in checkDeflateStatus, setParams case at java.base/java.util.zip.Deflater.deflateBytesBytes(Native Method) at java.base/java.util.zip.Deflater.deflate(Deflater.java:586) at java.base/java.util.zip.Deflater.deflate(Deflater.java:465) at FlushableGZIPOutputStream.deflate(InflateIn_DeflateOut0.java:393) at FlushableGZIPOutputStream.flush(InflateIn_DeflateOut0.java:373) at InflateIn_DeflateOut.TestFlushableGZIPOutputStream(InflateIn_DeflateOut.java:162) at InflateIn_DeflateOut.realMain(InflateIn_DeflateOut.java:305) at InflateIn_DeflateOut.main(InflateIn_DeflateOut.java:322)

environment: java -version java version "17.0.7" 2023-04-18 IBM Semeru Runtime Certified Edition 17.0.7.0 (build 17.0.7+7) Eclipse OpenJ9 VM 17.0.7.0 (build openj9-0.38.0, JRE 17 Linux ppc64le-64-Bit Compressed References 20230418_410 (JIT enabled, AOT enabled) OpenJ9 - d57d05932 OMR - 855813495 JCL - 7a1e0864e99 based on jdk-17.0.7+7)

cat /etc/redhat-release Red Hat Enterprise Linux release 8.6 (Ootpa) [root@p10nxgzip new]# uname -a Linux p10nxgzip 4.18.0-372.9.1.el8.ppc64le #1 SMP Fri Apr 15 21:55:01 EDT 2022 ppc64le ppc64le ppc64le GNU/Linux

I analysed the issue, it is related with nxgzip related when jdk native method, so I attached the jdk source and nxgzip function related for your review. res result is not expected, and related is from Java_java_util_zip_Deflater_deflateBufferBytes related function.

the error "unknown error in checkDeflateStatus, setParams case" is from jdk source, it is as follow:

static jlong checkDeflateStatus(JNIEnv env, jlong addr, jint inputLen, jint outputLen, jint params, int res) { z_stream strm = jlong_to_ptr(addr); jint inputUsed = 0, outputUsed = 0; int finished = 0; int setParams = params & 1;

if (setParams) {
    switch (res) {
    case Z_OK:
        setParams = 0;
        /* fall through */
    case Z_BUF_ERROR:
        inputUsed = inputLen - strm->avail_in;
        outputUsed = outputLen - strm->avail_out;
        break;
    default:
        throwInternalErrorHelper(env, strm, "unknown error in checkDeflateStatus, setParams case");  <======error is here
        return 0;
    }
} else {
    switch (res) {
    case Z_STREAM_END:
        finished = 1;
        /* fall through */
    case Z_OK:
    case Z_BUF_ERROR:
        inputUsed = inputLen - strm->avail_in;
        outputUsed = outputLen - strm->avail_out;
        break;
    default:
        throwInternalErrorHelper(env, strm, "unknown error in checkDeflateStatus");
        return 0;
    }
}
return ((jlong)inputUsed) | (((jlong)outputUsed) << 31) | (((jlong)finished) << 62) | (((jlong)setParams) << 63);

}

Java_java_util_zip_Deflater_deflateBufferBytes(JNIEnv env, jobject this, jlong addr, jlong inputBuffer, jint inputLen, jbyteArray outputArray, jint outputOff, jint outputLen, jint flush, jint params) { jbyte input = jlong_to_ptr(inputBuffer); jbyte output = (env)->GetPrimitiveArrayCritical(env, outputArray, 0); jlong retVal; jint res; if (output == NULL) { if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL) JNU_ThrowOutOfMemoryError(env, 0); return 0L; }

res = doDeflate(env, addr, input, inputLen, output + outputOff, outputLen,
                flush, params);     <========res is from doDeflate,but it is related with nxgzip dynamic library.
(*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0);

retVal = checkDeflateStatus(env, addr, inputLen, outputLen, params, res);
return retVal;

}

static jint doDeflate(JNIEnv env, jlong addr, jbyte input, jint inputLen, jbyte output, jint outputLen, jint flush, jint params) { z_stream strm = jlong_to_ptr(addr); int setParams = params & 1; int res;

strm->next_in  = (Bytef *) input;
strm->next_out = (Bytef *) output;
strm->avail_in  = inputLen;
strm->avail_out = outputLen;

if (setParams) {
    int strategy = (params >> 1) & 3;
    int level = params >> 3;
    res = deflateParams(strm, level, strategy); <======please review the function definition.
} else {
    res = deflate(strm, flush); <======= nxgzip function
}
return res;

}

int ZEXPORT deflateParams(strm, level, strategy) z_streamp strm; int level; int strategy; { deflate_state *s; compress_func func;

if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
s = strm->state;

ifdef FASTEST

if (level != 0) level = 1;

else

if (level == Z_DEFAULT_COMPRESSION) level = 6;

endif

if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
    return Z_STREAM_ERROR;
}
func = configuration_table[s->level].func;

if ((strategy != s->strategy || func != configuration_table[level].func) &&
    s->last_flush != -2) {
    /* Flush the last buffer: */
    int err = deflate(strm, Z_BLOCK);
    if (err == Z_STREAM_ERROR)
        return err;
    if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead)
        return Z_BUF_ERROR;
}
if (s->level != level) {
    if (s->level == 0 && s->matches != 0) {
        if (s->matches == 1)
            slide_hash(s);
        else
            CLEAR_HASH(s);
        s->matches = 0;
    }
    s->level = level;
    s->max_lazy_match   = configuration_table[level].max_lazy;
    s->good_match       = configuration_table[level].good_length;
    s->nice_match       = configuration_table[level].nice_length;
    s->max_chain_length = configuration_table[level].max_chain;
}
s->strategy = strategy;
return Z_OK;

}

during testing, I found the deflate from nxgzip returned 0xfffffffffffffffb and 0, it need to your help to find the root cause. ... if (setParams) { int strategy = (params >> 1) & 3; int level = params >> 3; res = deflateParams(strm, level, strategy); } else { res = deflate(strm, flush); } ...

deflate result is as follow: main 417895 [008] 775333.649302: probe_libnxz:deflate: (2000000915c8) strm=0x2000041adae0 flush=0 2000000915c8 deflate+0x8 (/root/fj/power-gzip-0.63/lib/.libs/libnxz.so.0.0.63) 20004e642c17 Java_java_util_zip_Deflater_deflateBytesBytes+0xe7 (/root/jdk-17.0.7+7/lib/libzip.so)

main 417895 [008] 775333.649308: probe_libnxz:deflate__return: (2000000915c8 <- 20004e642c18) arg1=0x0 20004e642c18 Java_java_util_zip_Deflater_deflateBytesBytes+0xe8 (/root/jdk-17.0.7+7/lib/libzip.so)

main 417895 [008] 775333.649317: probe_libnxz:deflate: (2000000915c8) strm=0x2000041adae0 flush=0 2000000915c8 deflate+0x8 (/root/fj/power-gzip-0.63/lib/.libs/libnxz.so.0.0.63) 20004e642c17 Java_java_util_zip_Deflater_deflateBytesBytes+0xe7 (/root/jdk-17.0.7+7/lib/libzip.so)

main 417895 [008] 775333.649320: probe_libnxz:deflate__return: (2000000915c8 <- 20004e642c18) arg1=0xfffffffffffffffb 20004e642c18 Java_java_util_zip_Deflater_deflateBytesBytes+0xe8 (/root/jdk-17.0.7+7/lib/libzip.so)

main 417895 [008] 775333.649444: probe_libnxz:deflate: (2000000915c8) strm=0x2000041adae0 flush=0 2000000915c8 deflate+0x8 (/root/fj/power-gzip-0.63/lib/.libs/libnxz.so.0.0.63)

main 417895 [008] 775333.649447: probe_libnxz:deflate__return: (2000000915c8 <- 20004e642c18) arg1=0x0 20004e642c18 Java_java_util_zip_Deflater_deflateBytesBytes+0xe8 (/root/jdk-17.0.7+7/lib/libzip.so) main 417895 [008] 775333.649479: probe_libnxz:deflate: (2000000915c8) strm=0x2000041adae0 flush=0 2000000915c8 deflate+0x8 (/root/fj/power-gzip-0.63/lib/.libs/libnxz.so.0.0.63) 20004e642c17 Java_java_util_zip_Deflater_deflateBytesBytes+0xe7 (/root/jdk-17.0.7+7/lib/libzip.so)

main 417895 [008] 775333.649482: probe_libnxz:deflate__return: (2000000915c8 <- 20004e642c18) arg1=0x0 20004e642c18 Java_java_util_zip_Deflater_deflateBytesBytes+0xe8 (/root/jdk-17.0.7+7/lib/libzip.so)

chenhealth1234 commented 1 year ago

I aatached the testing source code for your checking, and you can make the issue occur.

compile: javac InflateIn_DeflateOut.java run command: java InflateIn_DeflateOut

the source code of InflateIn_DeflateOut.java
/*

/**

import java.io.; import java.util.; import java.util.zip.*; import java.util.Scanner; public class InflateIn_DeflateOut {

private static class PairedInputStream extends ByteArrayInputStream {
    private PairedOutputStream out = null;
    private Random random;

    public PairedInputStream() {
        // The ByteArrayInputStream needs to start with a buffer, but we
        // need to set it to have no data
        super(new byte[1]);
        count = 0;
        pos = 0;
        random = new Random(new Date().getTime());
    }

    public void setPairedOutputStream(PairedOutputStream out) {
        this.out = out;
    }

    private void maybeFlushPair() {
        if (random.nextInt(100) < 10) {
            out.flush();
        }
    }

    public int read() {
        maybeFlushPair();
        return super.read();
    }

    public int read(byte b[], int off, int len) {
        maybeFlushPair();
        return super.read(b, off, len);
    }

    public void addBytes(byte[] bytes, int len) {
        int oldavail = count - pos;
        int newcount = oldavail + len;
        byte[] newbuf = new byte[newcount];
        System.arraycopy(buf, pos, newbuf, 0, oldavail);
        System.arraycopy(bytes, 0, newbuf, oldavail, len);
        pos = 0;
        count = newcount;
        buf = newbuf;
    }
}

private static class PairedOutputStream extends ByteArrayOutputStream {
    private PairedInputStream pairedStream = null;

    public PairedOutputStream(PairedInputStream inputPair) {
        super();
        this.pairedStream = inputPair;
    }

    public void flush() {
        if (count > 0) {
            pairedStream.addBytes(buf, count);
            reset();
        }
    }

    public void close() {
        flush();
    }
}

private static boolean readFully(InputStream in, byte[] buf, int length)
        throws IOException {
    int pos = 0;
    int n;
    while ((n = in.read(buf, pos, length - pos)) > 0) {
        pos += n;
        if (pos == length) return true;
    }
    return false;
}

private static boolean readLineIfAvailable(InputStream in, StringBuilder sb)
        throws IOException {
    try {
        while (in.available() > 0) {
            int i = in.read();
            if (i < 0) break;
            char c = (char) (((byte) i) & 0xff);
            sb.append(c);
            if (c == '\n') return true;
        }
    } catch (EOFException e) {
      // empty
    }
    return false;
}

/** Check that written, closed and read */
private static void WriteCloseRead() throws Throwable {
    Random random = new Random(new Date().getTime());

    PairedInputStream pis = new PairedInputStream();
    InflaterInputStream iis = new InflaterInputStream(pis);

    PairedOutputStream pos = new PairedOutputStream(pis);
    pis.setPairedOutputStream(pos);

    byte[] data = new byte[random.nextInt(1024 * 1024)];
    byte[] buf = new byte[data.length];
    random.nextBytes(data);

    try (DeflaterOutputStream dos = new DeflaterOutputStream(pos, true)) {
        dos.write(data);
    }
    check(readFully(iis, buf, buf.length));
    check(Arrays.equals(data, buf));
}

private static void TestFlushableGZIPOutputStream() throws Throwable {
    Random random = new Random(new Date().getTime());

    ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();
    OutputStream output = new FlushableGZIPOutputStream(byteOutStream);

    byte[] data = new byte[random.nextInt(1024 * 1024)];
    random.nextBytes(data);

    output.write(data);
    for (int i=0; i<data.length; i++) {
        output.write(data[i]);
    }
    output.flush();
    for (int i=0; i<data.length; i++) {
        output.write(data[i]);
    }
    output.write(data);
    output.close();

    ByteArrayInputStream byteInStream =
            new ByteArrayInputStream(byteOutStream.toByteArray());

    GZIPInputStream gzis = new GZIPInputStream(byteInStream);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    int numRead;
    byte[] b = new byte[4 * 1024];
    try {
        while ((numRead = gzis.read(b)) >= 0) {
            baos.write(b, 0, numRead);
        }
    } finally {
        baos.close();
    }

    byte[] decompressedBytes = baos.toByteArray();

    check(decompressedBytes.length == data.length * 4);
}

private static void check(InputStream is, OutputStream os)
    throws Throwable
{
    Random random = new Random(new Date().getTime());
   // Large writes
    for (int x = 0; x < 200 ; x++) {
        // byte[] data = new byte[random.nextInt(1024 * 1024)];
        byte[] data = new byte[1024];
        byte[] buf = new byte[data.length];
        random.nextBytes(data);

        os.write(data);
        os.flush();
        check(readFully(is, buf, buf.length));
        check(Arrays.equals(data, buf));
    }

    // Small writes
    for (int x = 0; x < 2000 ; x++) {
        byte[] data = new byte[random.nextInt(20) + 10];
        byte[] buf = new byte[data.length];
        random.nextBytes(data);

        os.write(data);
        os.flush();
        if (!readFully(is, buf, buf.length)) {
            fail("Didn't read full buffer of " + buf.length);
        }
        check(Arrays.equals(data, buf));
    }

    String quit = "QUIT\r\n";

    // Close it out
    os.write(quit.getBytes());
    os.close();

    StringBuilder sb = new StringBuilder();
    check(readLineIfAvailable(is, sb));
    equal(sb.toString(), quit);
}

/** Check that written, flushed and read */
private static void WriteFlushRead() throws Throwable {
    PairedInputStream pis = new PairedInputStream();
    InflaterInputStream iis = new InflaterInputStream(pis);

    PairedOutputStream pos = new PairedOutputStream(pis);
    pis.setPairedOutputStream(pos);
    DeflaterOutputStream dos = new DeflaterOutputStream(pos, true);

    check(iis, dos);
}

private static void GZWriteFlushRead() throws Throwable {
    PairedInputStream pis = new PairedInputStream();
    PairedOutputStream pos = new PairedOutputStream(pis);
    pis.setPairedOutputStream(pos);

    GZIPOutputStream gos = new GZIPOutputStream(pos, true);
    gos.flush();  // flush the head out, so gis can read
    GZIPInputStream gis = new GZIPInputStream(pis);

    check(gis, gos);
}

private static void checkLOP(InputStream is, OutputStream os)
    throws Throwable
{
    boolean flushed = false;
    int count = 0;

    // Do at least a certain number of lines, but too many without a
    // flush means this test isn't testing anything
    while ((count < 10 && flushed) || (count < 1000 && !flushed)) {
        String command = "PING " + count + "\r\n";
        os.write(command.getBytes());

        StringBuilder buf = new StringBuilder();
        if (!readLineIfAvailable(is, buf)) {
            flushed = true;
            os.flush();
            check(readLineIfAvailable(is, buf));
        }
        equal(buf.toString(), command);
        count++;
    }
    check(flushed);
}

/** Validate that we need to use flush at least once on a line
 * oriented protocol */
private static void LineOrientedProtocol() throws Throwable {
    PairedInputStream pis = new PairedInputStream();
    InflaterInputStream iis = new InflaterInputStream(pis);

    PairedOutputStream pos = new PairedOutputStream(pis);
    pis.setPairedOutputStream(pos);
    DeflaterOutputStream dos = new DeflaterOutputStream(pos, true);

    checkLOP(iis, dos);
}

private static void GZLineOrientedProtocol() throws Throwable {
    PairedInputStream pis = new PairedInputStream();
    PairedOutputStream pos = new PairedOutputStream(pis);
    pis.setPairedOutputStream(pos);

    GZIPOutputStream gos = new GZIPOutputStream(pos, true);
    gos.flush();  // flush the head out, so gis can read
    GZIPInputStream gis = new GZIPInputStream(pis);

    checkLOP(gis, gos);
}

public static void realMain(String[] args) throws Throwable {
    TestFlushableGZIPOutputStream();
}

//--------------------- Infrastructure ---------------------------
static volatile int passed = 0, failed = 0;
static void pass() {passed++;}
static void fail() {failed++; Thread.dumpStack();}
static void fail(String msg) {System.out.println(msg); fail();}
static void unexpected(Throwable t) {failed++; t.printStackTrace();}
static void check(boolean cond) {if (cond) pass(); else fail();}
static void equal(Object x, Object y) {
    if (x == null ? y == null : x.equals(y)) pass();
    else fail(x + " not equal to " + y);}
public static void main(String[] args) throws Throwable {
   //Scanner scanner = new Scanner(System.in);

//  String line = scanner.nextLine();
    try {realMain(args);} catch (Throwable t) {unexpected(t);}
    System.out.println("\nPassed = " + passed + " failed = " + failed);
    if (failed > 0) throw new AssertionError("Some tests failed");}

}

class FlushableGZIPOutputStream extends GZIPOutputStream { public FlushableGZIPOutputStream(OutputStream os) throws IOException { super(os); }

private static final byte[] EMPTYBYTEARRAY = new byte[0];
private boolean hasData = false;

/**
 * Here we make sure we have received data, so that the header has been for
 * sure written to the output stream already.
 */
@Override
public synchronized void write(byte[] bytes, int i, int i1)
        throws IOException {
    super.write(bytes, i, i1);
    hasData = true;
}

@Override
public synchronized void write(int i) throws IOException {
    super.write(i);
    hasData = true;
}

@Override
public synchronized void write(byte[] bytes) throws IOException {
    super.write(bytes);
    hasData = true;
}

@Override
public synchronized void flush() throws IOException {
    if (!hasData) {
        return; // do not allow the gzip header to be flushed on its own
    }

    // trick the deflater to flush
    /**
     * Now this is tricky: We force the Deflater to flush its data by
     * switching compression level. As yet, a perplexingly simple workaround
     * for
     * http://developer.java.sun.com/developer/bugParade/bugs/4255743.html
     */
    if (!def.finished()) {
        def.setInput(EMPTYBYTEARRAY, 0, 0);

        def.setLevel(Deflater.NO_COMPRESSION);
        deflate();

        def.setLevel(Deflater.DEFAULT_COMPRESSION);
        deflate();

        out.flush();
    }

    hasData = false; // no more data to flush
}

/*
 * Keep on calling deflate until it runs dry. The default implementation
 * only does it once and can therefore hold onto data when they need to be
 * flushed out.
 */
@Override
protected void deflate() throws IOException {
    int len;
    do {
        len = def.deflate(buf, 0, buf.length);
        if (len > 0) {
            out.write(buf, 0, len);
        }
    } while (len != 0);
}

}

edwin-wang commented 1 year ago

@chenhealth1234 Could you help narrow down this case to libnxz library which will help us understand this issue?

chenhealth1234 commented 1 year ago

Dear ,

The problematic return values(0xfffffffffffffffb) are from nx_deflate. We can see that nx_deflate implementation differs in v0.64 from v0.63, could you help to take a look? Thanks.

Related Info is as follow: main 417895 [008] 775333.649302: probe_libnxz:deflate: (2000000915c8) strm=0x2000041adae0 flush=0 2000000915c8 deflate+0x8 (/root/fj/power-gzip-0.63/lib/.libs/libnxz.so.0.0.63) 20004e642c17 Java_java_util_zip_Deflater_deflateBytesBytes+0xe7 (/root/jdk-17.0.7+7/lib/libzip.so)

main 417895 [008] 775333.649308: probe_libnxz:deflate__return: (2000000915c8 <- 20004e642c18) arg1=0x0 20004e642c18 Java_java_util_zip_Deflater_deflateBytesBytes+0xe8 (/root/jdk-17.0.7+7/lib/libzip.so)

main 417895 [008] 775333.649317: probe_libnxz:deflate: (2000000915c8) strm=0x2000041adae0 flush=0 2000000915c8 deflate+0x8 (/root/fj/power-gzip-0.63/lib/.libs/libnxz.so.0.0.63) 20004e642c17 Java_java_util_zip_Deflater_deflateBytesBytes+0xe7 (/root/jdk-17.0.7+7/lib/libzip.so)

main 417895 [008] 775333.649320: probe_libnxz:deflate__return: (2000000915c8 <- 20004e642c18) arg1=0xfffffffffffffffb 20004e642c18 Java_java_util_zip_Deflater_deflateBytesBytes+0xe8 (/root/jdk-17.0.7+7/lib/libzip.so)

main 417895 [008] 775333.649444: probe_libnxz:deflate: (2000000915c8) strm=0x2000041adae0 flush=0 2000000915c8 deflate+0x8 (/root/fj/power-gzip-0.63/lib/.libs/libnxz.so.0.0.63)

main 417895 [008] 775333.649447: probe_libnxz:deflate__return: (2000000915c8 <- 20004e642c18) arg1=0x0 20004e642c18 Java_java_util_zip_Deflater_deflateBytesBytes+0xe8 (/root/jdk-17.0.7+7/lib/libzip.so) main 417895 [008] 775333.649479: probe_libnxz:deflate: (2000000915c8) strm=0x2000041adae0 flush=0 2000000915c8 deflate+0x8 (/root/fj/power-gzip-0.63/lib/.libs/libnxz.so.0.0.63) 20004e642c17 Java_java_util_zip_Deflater_deflateBytesBytes+0xe7 (/root/jdk-17.0.7+7/lib/libzip.so)

main 417895 [008] 775333.649482: probe_libnxz:deflate__return: (2000000915c8 <- 20004e642c18) arg1=0x0 20004e642c18 Java_java_util_zip_Deflater_deflateBytesBytes+0xe8 (/root/jdk-17.0.7+7/lib/libzip.so)

sachinmonga64 commented 1 year ago

@chenhealth1234 We have some questions before we proceed debugging.

  1. Is this the newly developed application or it has been developed and used for a while now ?
  2. Who uses this application ?
  3. Why 0.63 version is used and not 0.64 version ? There have been major changes since 0.63which needs to be adapted.
  4. Where is the device initialization happening ? There is no code related to deflateInit () or deflateEnd(). As per my understanding so far with libnxz , we cannot call deflate() without Initializing the device. And then we have to properly close the device. But there is nothing like this in the shared code.
  5. After the above points are answered , in the next step , we may need the strm structure values so that we can test our own application with the same values and check the result value which is causing the exception here.
chenhealth1234 commented 1 year ago

Dear ,

I answer the question, the info is as follow for your review:

Is this the newly developed application or it has been developed and used for a while now ? Java code is developed and used for a while, but first integration testing with nxgzip. Who uses this application ? We need to approve nxgzip in power10 is great by java testing. If it is ok, we plan to introduce this feature to the customer who would like to use the power10 platform.

Why 0.63 version is used and not 0.64 version ? There have been major changes since 0.63 which needs to be adapted. We met some blocked issue sucha as EOF exception by the issue when using 0.64 version. If 0.64 version can be used, we hope to use 0.64 version.

Where is the device initialization happening ? There is no code related to deflateInit () or deflateEnd(). As per my understanding so far with libnxz , we cannot call deflate() without Initializing the device. And then we have to properly close the device. But there is nothing like this in the shared code. InflateIn_DeflateOut.java is a whole java testing code, feel free to do testing, if any issue, let me know. Thanks.

edwin-wang commented 1 year ago

@sachinmonga64 For Q3, we met an EOF exception issue while using 0.64. And it has been submitted in another issue - https://github.com/libnxz/power-gzip/issues/203.

sachinmonga64 commented 1 year ago

As we analysed the Java application above, we have confirmed that the java method setlevel()is causing trouble to the libnxz. The java code sets the level as NO_COMPRESSION before calling deflate( ) and then it changes its level to DEFAULT_COMPRESSION and calls the deflate()again.

Although setlevel() sets NO_COMPRESSION which has the value 0but libnxz recieves this value as -1. So, It looks that either setlevel()method is not able to set NO_COMPRESSION level until the current deflate( ) is executed OR there is some intermediatery code which changes this value.

We need to analyse further the setlevel() method and its interface with libnxz.

On the other hand , if we are able to change the Java code to specify the compression level in the constructor itself, then the problem does not arise. For example, consider the below code which gives the same exception as the original code shared above when using setlevel()

]$ cat Sample_Deflate.java 

import java.util.zip.*;
import java.io.UnsupportedEncodingException;

class Sample_Deflate {

  public static void main(String args[])
    throws UnsupportedEncodingException
  {

    String pattern = "Starbucks", text = "";

    for (int i = 0; i < 4; i++)
      text += pattern;

    System.out.println("Original String :" + text
            + "\n Size " + text.length());

    Deflater d = new Deflater(Deflater.NO_COMPRESSION);   //////////// Use Compression level in COnstructor instead.
    //d.setLevel(Deflater.NO_COMPRESSION);

    d.setInput(text.getBytes("UTF-8"));

    d.finish();

    byte output[] = new byte[1024];

    int size = d.deflate(output);

    System.out.println("Compressed String with level ="
              + new String(output)
              + "\n Size " + size);

    d.end();
    System.out.printf("Deflater.NO_COMPRESSION: %d",Deflater.NO_COMPRESSION);

  }
}

So, we can have some workaround code change to specify compression in constructor until we debug setlevel() further. Also, I want to understand the below comment in the application and also how it is able to work with zlib code (without PRELOAD)

 // trick the deflater to flush
  /**
   * Now this is tricky: We force the Deflater to flush its data by
   * switching compression level. As yet, a perplexingly simple workaround
   * for
   * http://developer.java.sun.com/developer/bugParade/bugs/4255743.html
chenhealth1234 commented 1 year ago

Dear , Thanks a lot for your quick answer, may I ask for your help to find a way to make sure the java tseting code running like zlib integrated running normally? libnxz recieves this level value as -1, can you help to point out the detailed place? Thanks.

from java side, some info is for your review.

public void setLevel(int level) { if ((level < 0 || level > 9) && level != DEFAULT_COMPRESSION) { throw new IllegalArgumentException("invalid compression level"); } synchronized (zsRef) { if (this.level != level) { this.level = level; setParams = true; } } }

int ZEXPORT deflateParams(strm, level, strategy) z_streamp strm; int level; int strategy; { deflate_state *s; compress_func func;

if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
s = strm->state;

ifdef FASTEST

if (level != 0) level = 1;

else

if (level == Z_DEFAULT_COMPRESSION) level = 6;

endif

if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
    return Z_STREAM_ERROR;
}
func = configuration_table[s->level].func;

if ((strategy != s->strategy || func != configuration_table[level].func) &&
    s->last_flush != -2) {
    /* Flush the last buffer: */
    int err = deflate(strm, Z_BLOCK);
    if (err == Z_STREAM_ERROR)
        return err;
    if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead)
        return Z_BUF_ERROR;
}
if (s->level != level) {
    if (s->level == 0 && s->matches != 0) {
        if (s->matches == 1)
            slide_hash(s);
        else
            CLEAR_HASH(s);
        s->matches = 0;
    }
    s->level = level;
    s->max_lazy_match   = configuration_table[level].max_lazy;
    s->good_match       = configuration_table[level].good_length;
    s->nice_match       = configuration_table[level].nice_length;
    s->max_chain_length = configuration_table[level].max_chain;
}
s->strategy = strategy;
return Z_OK;

}

If any needed from testing, feel free to let me know. Thanks.

sachinmonga64 commented 1 year ago

Hi

Thanks for sharing the code.

The investigation boils down to as follows:

the deflate( ) call in the java code after setlevel( ) called to change the compression level (any level other than DEFAULT_COMPRESSION) leads to calling of deflateParams( )function from the zlib.

Actually, the deflateParams( )equivalent function is missing in libnxz. The deflateParams() function from zlib dynamically changes the compression level and the compression strategy.

Just for testing, If we provide do nothing function for the symbol deflateParams() in libnxz then the error is resolved. Of-course , the compression level setting wont' happen.

int deflateParams(z_streamp strm, int level, int strategy)
{
        return 0;
}
]$ LD_PRELOAD=/home/sachin/java_libnxz/power-gzip/lib/.libs/libnxz.so java InflateIn_DeflateOut
Passed = 1 failed = 0

So, we will investigate further challenges to provide the function definition of deflateParams()from libnxz.

chenhealth1234 commented 1 year ago

Dear ,

Appreciate a lot for your great support, it is actually ok, look forward to the latest version. Thanks again.

chenhealth1234 commented 1 year ago

Dear ,

After I added the deflateParams into nxgzip source code as your sharing, I found the testing CopyZipFile.java which now test failed, it is related with the deflateParams function involed issue.

The tested result is as follow for your review.

[root@p10nxgzip zip]# LD_PRELOAD=/root/ck/power-gzip-0.63/lib/.libs/libnxz.so java CopyZipFile name=test1.txt, clen=-1, len=-1, crc=-1 name=test1.txt, clen=8, len=12, crc=85301268

name=test2.txt, clen=12, len=12, crc=85301268 name=test2.txt, clen=12, len=12, crc=85301268

name=test3.txt, clen=-1, len=-1, crc=-1 name=test3.txt, clen=8, len=12, crc=85301268

name=test4.txt, clen=-1, len=-1, crc=-1 name=test4.txt, clen=8, len=12, crc=85301268

name=test5.txt, clen=-1, len=-1, crc=-1 name=test5.txt, clen=8, len=12, crc=85301268

name=test1.txt, clen=8, len=12, crc=85301268

name=test2.txt, clen=12, len=12, crc=85301268

name=test3.txt, clen=8, len=12, crc=85301268

name=test4.txt, clen=8, len=12, crc=85301268

name=test5.txt, clen=8, len=12, crc=85301268

entry name = test1.txt

entry name = test2.txt

entry name = test3.txt

Exception in thread "main" java.lang.Exception: Should throw a ZipException if ZipEntry.setCompressedSize() was called. at CopyZipFile.main(CopyZipFile.java:183)

chenhealth1234 commented 1 year ago

After the deflateParams involved in nxgzip library, there is some error such as the dictionary related failed info as follow, so I paste the error info for your review. Let me know if any needed. Thanks a lot.

LD_PRELOAD=/root/ck/power-gzip-0.63/lib/.libs/libnxz.so java DeInflate level:-1, strategy: 0, dowrap: false level:-1, strategy: 0, dowrap: true Exception in thread "main" java.lang.RuntimeException: checkDict failed: need dict to continue at DeInflate.checkDict(DeInflate.java:223) at DeInflate.main(DeInflate.java:300)

LD_PRELOAD=/root/ck/power-gzip-0.63/lib/.libs/libnxz.so java DeInflateIn_InflateOut Error: Could not find or load main class DeInflateIn_InflateOut Caused by: java.lang.ClassNotFoundException: DeInflateIn_InflateOut [root@p10nxgzip zip]# LD_PRELOAD=/root/ck/power-gzip-0.63/lib/.libs/libnxz.so java DeflateIn_InflateOut java.lang.Exception: Stack trace at java.base/java.lang.Thread.dumpStack(Thread.java:1380) at DeflateIn_InflateOut.fail(DeflateIn_InflateOut.java:298) at DeflateIn_InflateOut.fail(DeflateIn_InflateOut.java:292) at DeflateIn_InflateOut.check(DeflateIn_InflateOut.java:301) at DeflateIn_InflateOut.ByteReadArrayWrite(DeflateIn_InflateOut.java:132) at DeflateIn_InflateOut.realMain(DeflateIn_InflateOut.java:280) at DeflateIn_InflateOut.main(DeflateIn_InflateOut.java:307) Must throw ZipException without dictionary java.lang.Exception: Stack trace at java.base/java.lang.Thread.dumpStack(Thread.java:1380) at DeflateIn_InflateOut.fail(DeflateIn_InflateOut.java:298) at DeflateIn_InflateOut.check(DeflateIn_InflateOut.java:302) at DeflateIn_InflateOut.NeedsDictionary(DeflateIn_InflateOut.java:253) at DeflateIn_InflateOut.realMain(DeflateIn_InflateOut.java:286) at DeflateIn_InflateOut.main(DeflateIn_InflateOut.java:307)

Passed = 17 failed = 2 Exception in thread "main" java.lang.AssertionError: Some tests failed at DeflateIn_InflateOut.main(DeflateIn_InflateOut.java:309)

sachinmonga64 commented 1 year ago

Can you please paste what definition you added for deflateParams ?

Also please share the test cases if possible.

BTW, following test case was producing same error as originally reported and after I added deflateParams( ) definition , the error was resolved. However , original reported test program is giving Java runtime error now. So I am currently debugging that.

]$ cat Sample_Deflate.java
import java.util.zip.*;
import java.io.UnsupportedEncodingException;

class Sample_Deflate {

    public static void main(String args[])
        throws UnsupportedEncodingException
    {

        String pattern = "Starbucks", text = "";

        for (int i = 0; i < 4; i++)
            text += pattern;

        System.out.println("Original String :" + text
                + "\n Size " + text.length());

        Deflater d = new Deflater();
    d.setLevel(Deflater.NO_COMPRESSION);

        d.setInput(text.getBytes("UTF-8"));

        d.finish();
        byte output[] = new byte[1024];
        int size = d.deflate(output);

        System.out.println("Compressed String with level ="
                           + new String(output)
                           + "\n Size " + size);

        d.end();

    }
}
sachinmonga64 commented 1 year ago

If you could provide me your testcase which is having issue , I can test on my definition of deflateParams()

chenhealth1234 commented 1 year ago

Dear ,

the function definition: int deflateParams(z_streamp strm, int level, int strategy) { return 0; }

Testing java code is from the jdk testing part, after deflateParams involved, the CopyZipFile.java run failed, the testing code is as follow:

/*

/**

import java.io.File; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.CRC32; import java.util.zip.Deflater; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream;

public class CopyZipFile { private static final String ZIP_FILE = "first.zip"; private static final String TEST_STRING = "TestTestTest";

private static void createZip(String zipFile) throws Exception {
    File f = new File(zipFile);
    f.deleteOnExit();
    try (OutputStream os = new FileOutputStream(f);
         ZipOutputStream zos = new ZipOutputStream(os)) {
        // First file will be compressed with DEFAULT_COMPRESSION (i.e. -1 or 6)
        zos.putNextEntry(new ZipEntry("test1.txt"));
        zos.write(TEST_STRING.getBytes());
        zos.closeEntry();
        // Second file won't be compressed at all (i.e. STORED)
        zos.setMethod(ZipOutputStream.STORED);
        ZipEntry ze = new ZipEntry("test2.txt");
        int length = TEST_STRING.length();
        ze.setSize(length);
        ze.setCompressedSize(length);
        CRC32 crc = new CRC32();
        crc.update(TEST_STRING.getBytes("utf8"), 0, length);
        ze.setCrc(crc.getValue());
        zos.putNextEntry(ze);
        zos.write(TEST_STRING.getBytes());
        // Third file will be compressed with NO_COMPRESSION (i.e. 0)
        zos.setMethod(ZipOutputStream.DEFLATED);
        zos.setLevel(Deflater.NO_COMPRESSION);
        zos.putNextEntry(new ZipEntry("test3.txt"));
        zos.write(TEST_STRING.getBytes());
        // Fourth file will be compressed with BEST_SPEED (i.e. 1)
        zos.setLevel(Deflater.BEST_SPEED);
        zos.putNextEntry(new ZipEntry("test4.txt"));
        zos.write(TEST_STRING.getBytes());
        // Fifth file will be compressed with BEST_COMPRESSION (i.e. 9)
        zos.setLevel(Deflater.BEST_COMPRESSION);
        zos.putNextEntry(new ZipEntry("test5.txt"));
        zos.write(TEST_STRING.getBytes());
    }
}

public static void main(String args[]) throws Exception {
    // By default, ZipOutputStream creates zip files with Local File Headers
    // without size, compressedSize and crc values and an extra Data
    // Descriptor (see https://en.wikipedia.org/wiki/Zip_(file_format)
    // after the data belonging to that entry with these values if in the
    // corresponding ZipEntry one of the size, compressedSize or crc fields is
    // equal to '-1' (which is the default for newly created ZipEntries).
    createZip(ZIP_FILE);

    // Now read all the entries of the newly generated zip file with a ZipInputStream
    // and copy them to a new zip file with the help of a ZipOutputStream.
    // This only works reliably because the generated zip file has no values for the
    // size, compressedSize and crc values of a zip entry in the local file header and
    // therefore the ZipEntry objects created by ZipOutputStream.getNextEntry() will have
    // all these fields set to '-1'.
    ZipEntry entry;
    byte[] buf = new byte[512];
    try (InputStream is = new FileInputStream(ZIP_FILE);
         ZipInputStream zis = new ZipInputStream(is);
         OutputStream os = new ByteArrayOutputStream();
         ZipOutputStream zos = new ZipOutputStream(os)) {
        while((entry = zis.getNextEntry())!=null) {
            // ZipInputStream.getNextEntry() only reads the Local File Header of a zip entry,
            // so for the zip file we've just generated the ZipEntry fields 'size', 'compressedSize`
            // and 'crc' for deflated entries should be uninitialized (i.e. '-1').
            System.out.println(
                String.format("name=%s, clen=%d, len=%d, crc=%d",
                              entry.getName(), entry.getCompressedSize(), entry.getSize(), entry.getCrc()));
            if (entry.getMethod() == ZipEntry.DEFLATED &&
                (entry.getCompressedSize() != -1 || entry.getSize() != -1 || entry.getCrc() != -1)) {
                throw new Exception("'size', 'compressedSize' and 'crc' shouldn't be initialized at this point.");
            }
            zos.putNextEntry(entry);
            zis.transferTo(zos);
            // After all the data belonging to a zip entry has been inflated (i.e. after ZipInputStream.read()
            // returned '-1'), it is guaranteed that the ZipInputStream will also have consumed the Data
            // Descriptor (if any) after the data and will have updated the 'size', 'compressedSize' and 'crc'
            // fields of the ZipEntry object.
            System.out.println(
                String.format("name=%s, clen=%d, len=%d, crc=%d\n",
                              entry.getName(), entry.getCompressedSize(), entry.getSize(), entry.getCrc()));
            if (entry.getCompressedSize() == -1 || entry.getSize() == -1) {
                throw new Exception("'size' and 'compressedSize' must be initialized at this point.");
            }
        }
    }

    // Now we read all the entries of the initially generated zip file with the help
    // of the ZipFile class. The ZipFile class reads all the zip entries from the Central
    // Directory which must have accurate information for size, compressedSize and crc.
    // This means that all ZipEntry objects returned from ZipFile will have correct
    // settings for these fields.
    // If the compression level was different in the initial zip file (which we can't find
    // out any more now because the zip file format doesn't record this information) the
    // size of the re-compressed entry we are writing to the ZipOutputStream might differ
    // from the original compressed size recorded in the ZipEntry. This would result in an
    // "invalid entry compressed size" ZipException if ZipOutputStream wouldn't ignore
    // the implicitely set compressed size attribute of ZipEntries read from a ZipFile
    // or ZipInputStream.
    try (OutputStream os = new ByteArrayOutputStream();
         ZipOutputStream zos = new ZipOutputStream(os);
         ZipFile zf = new ZipFile(ZIP_FILE)) {
        Enumeration<? extends ZipEntry> entries = zf.entries();
        while (entries.hasMoreElements()) {
            entry = entries.nextElement();
            System.out.println(
                String.format("name=%s, clen=%d, len=%d, crc=%d\n",
                              entry.getName(), entry.getCompressedSize(),
                              entry.getSize(), entry.getCrc()));
            if (entry.getCompressedSize() == -1 || entry.getSize() == -1) {
                throw new Exception("'size' and 'compressedSize' must be initialized at this point.");
            }
            InputStream is = zf.getInputStream(entry);
            zos.putNextEntry(entry);
            is.transferTo(zos);
            zos.closeEntry();
        }
    }

    // The compressed size attribute of a ZipEntry shouldn't be ignored if it was set
    // explicitely by calling ZipEntry.setCpompressedSize()
    try (OutputStream os = new ByteArrayOutputStream();
         ZipOutputStream zos = new ZipOutputStream(os);
         ZipFile zf = new ZipFile(ZIP_FILE)) {
        Enumeration<? extends ZipEntry> entries = zf.entries();
        while (entries.hasMoreElements()) {
            try {
                entry = entries.nextElement();
                entry.setCompressedSize(entry.getCompressedSize());
                InputStream is = zf.getInputStream(entry);
                zos.putNextEntry(entry);
                is.transferTo(zos);
                zos.closeEntry();
                System.out.println( String.format("entry name = %s\n", entry.getName()));
                if ("test3.txt".equals(entry.getName())) {
                    throw new Exception(
                        "Should throw a ZipException if ZipEntry.setCompressedSize() was called.");
                }
            } catch (ZipException ze) {
                if ("test1.txt".equals(entry.getName()) || "test2.txt".equals(entry.getName())) {
                    throw new Exception(
                        "Shouldn't throw a ZipExcpetion for STORED files or files compressed with DEFAULT_COMPRESSION");
                }
                // Hack to fix and close the offending zip entry with the correct compressed size.
                // The exception message is something like:
                //   "invalid entry compressed size (expected 12 but got 7 bytes)"
                // and we need to extract the second integer.
                Pattern cSize = Pattern.compile("\\d+");
                Matcher m = cSize.matcher(ze.getMessage());
                m.find();
                m.find();
                entry.setCompressedSize(Integer.parseInt(m.group()));
            }
        }
    }
}

}

chenhealth1234 commented 1 year ago

LD_PRELOAD=/root/ck/power-gzip-0.63/lib/.libs/libnxz.so java CopyZipFile name=test1.txt, clen=-1, len=-1, crc=-1 name=test1.txt, clen=8, len=12, crc=85301268

name=test2.txt, clen=12, len=12, crc=85301268 name=test2.txt, clen=12, len=12, crc=85301268

name=test3.txt, clen=-1, len=-1, crc=-1 name=test3.txt, clen=8, len=12, crc=85301268

name=test4.txt, clen=-1, len=-1, crc=-1 name=test4.txt, clen=8, len=12, crc=85301268

name=test5.txt, clen=-1, len=-1, crc=-1 name=test5.txt, clen=8, len=12, crc=85301268

name=test1.txt, clen=8, len=12, crc=85301268

name=test2.txt, clen=12, len=12, crc=85301268

name=test3.txt, clen=8, len=12, crc=85301268

name=test4.txt, clen=8, len=12, crc=85301268

name=test5.txt, clen=8, len=12, crc=85301268

entry name = test1.txt

entry name = test2.txt

entry name = test3.txt

Exception in thread "main" java.lang.Exception: Should throw a ZipException if ZipEntry.setCompressedSize() was called. at CopyZipFile.main(CopyZipFile.java:183)

if no nxgzip used, the entry name result for test3.txt would be not here. The expected result is as follow: name=test1.txt, clen=-1, len=-1, crc=-1 name=test1.txt, clen=8, len=12, crc=85301268

name=test2.txt, clen=12, len=12, crc=85301268 name=test2.txt, clen=12, len=12, crc=85301268

name=test3.txt, clen=-1, len=-1, crc=-1 name=test3.txt, clen=19, len=12, crc=85301268

name=test4.txt, clen=-1, len=-1, crc=-1 name=test4.txt, clen=9, len=12, crc=85301268

name=test5.txt, clen=-1, len=-1, crc=-1 name=test5.txt, clen=8, len=12, crc=85301268

name=test1.txt, clen=8, len=12, crc=85301268

name=test2.txt, clen=12, len=12, crc=85301268

name=test3.txt, clen=19, len=12, crc=85301268

name=test4.txt, clen=9, len=12, crc=85301268

name=test5.txt, clen=8, len=12, crc=85301268

entry name = test1.txt

entry name = test2.txt

entry name = test5.txt

sachinmonga64 commented 1 year ago

Hi Not easy for me to understand the java test case you just shared.

But what I can tell you is that we have to provide the definition of deflateParams because only then it will change the compression level. I have tried to provide s/w definition of it and it is successful for simple inflater/deflater class. However I am facing further errors now from GZIPInputStream class in the originally shared test case as below:

java.util.zip.ZipException: Corrupt GZIP trailer
    at java.base/java.util.zip.GZIPInputStream.readTrailer(GZIPInputStream.java:226)
    at java.base/java.util.zip.GZIPInputStream.read(GZIPInputStream.java:120)
    at java.base/java.io.FilterInputStream.read(FilterInputStream.java:107)
    at InflateIn_DeflateOut.TestFlushableGZIPOutputStream(InflateIn_DeflateOut.java:173)
    at InflateIn_DeflateOut.realMain(InflateIn_DeflateOut.java:302)
    at InflateIn_DeflateOut.main(InflateIn_DeflateOut.java:319)

This new error seems to have different code flow than previous one hence I have to investigate further issues (after deflateParams resolution)

chenhealth1234 commented 1 year ago

Dear Sachin,

Appreciate a lot for your help and solving the issue. I will try to do java testing and give you what you hope to understand the issue easily, so let me know if any needed from java testing or other. Thanks again.

sachinmonga64 commented 1 year ago

@chenhealth1234

I have routed deflateParams symbol from libnxz to pick its definition from libz.so This resolves current 2 issues but is giving further error below.

Current error is that gzip trailer seems corrupted while inflating.

java.io.EOFException: Unexpected end of ZLIB input stream
    at java.base/java.util.zip.InflaterInputStream.fill(InflaterInputStream.java:245)
    at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:159)
    at java.base/java.util.zip.GZIPInputStream.read(GZIPInputStream.java:118)
    at java.base/java.io.FilterInputStream.read(FilterInputStream.java:107)
    at InflateIn_DeflateOut.TestFlushableGZIPOutputStream(InflateIn_DeflateOut.java:173)
    at InflateIn_DeflateOut.realMain(InflateIn_DeflateOut.java:302)
    at InflateIn_DeflateOut.main(InflateIn_DeflateOut.java:319)

libnxz adds some extra bytes while deflating butfill( )method of GZIPInputStream class is throwing exception on writing extra bytes. As proper tracing is not available in libnxz , I want to derive proper C/C++ equivalent case for this issue to debug further.

chenhealth1234 commented 1 year ago

Dear ,

Is there any process about inflating EOF issue, deflateParams definition or any related modification? Let me know if any needed. Thanks a lot.

sachinmonga64 commented 1 year ago

Hi

We are planning to support libnxz 0.63 version first. After having provided appropriate deflateParams definition , 0.63 cases are Passing except #204.

We are working on #204.

sachinmonga64 commented 1 year ago

Hi

We are planning to support libnxz 0.63 version first. After having provided appropriate deflateParams definition , 0.63 cases are Passing except #204.

We are working on #204.

chenhealth1234 commented 1 year ago

Got it, appreciate a lot for your great support. Thanks.

chenhealth1234 commented 1 year ago

Dear ,

Is there any latest process sharing? Looking forward to the latest version or any latest process, if any shared, feel free to let me know. Appreciate a lot for your great support.

sachinmonga64 commented 1 year ago

we have prepared a fix for this failure. We have executed our libnxz internal test-suites with the fix. There are multiple test-suites inside libnxz. After providing fixes of other tickets as well (#204, #203) , we will execute libnxz test-suites once again. Afterwards we will plan to merge it with 0.63

sachinmonga64 commented 1 year ago

Let me know if any specific information is required

chenhealth1234 commented 1 year ago

Dear , May I ask for your help to confirm how long the internal testing can be finished? When will the latest 0.63 version can be released? We will do local Java integration testing asap in case any issue need to be solved. Appreciate a lot for your great support.

sachinmonga64 commented 1 year ago

Dear , We have planned to finish the internal testing (for 0.63) in the first week of September. So , we are planning to release it latest by the 2nd week of September. However, since it includes buffer time , we would like to finish this all a week before.

sachinmonga64 commented 1 year ago

Hi

0.63-Provide-deflateParams-definition.patch

Please find attached 0.63 fix patch for #202 , #203 and #204(partial as commented on the ticket) Please apply it on 0.63 libnxz only (git am ) and execute the test-suite at your end. Only 1 failure out of 60 cases is expected(#204 partial)

Once you acknowledge, we will start plan for upstreaming it in 0.63

charleschen2000 commented 1 year ago

Could you help to provide a workaround solution for this issue: Instead of throwing exceptions, for any strategies that is NOT supported, just resort to the default strategy (Z_DEFAULT_STRATEGY). For any compression level that is NOT supported, resort to Z_DEFAULT_COMPRESSION.

Although those changes might slightly change the semantics, but it shall work without failure for most real customer scenarios.

sachinmonga64 commented 1 year ago

We will not be able to change unsupported strategies to DEFAULT_STRATEGY because of the following reason. From Java code, the strategies are declared/defined in inflate/deflate class and specified in the java program to change through setLevel and setStrategy which calls deflateParams( ) from libnxz . The java code expects the output data in that particular strategy format in which it is calling setStrategy as a parameter else it throws an exception DataFormatException

Now even if we change in libnxz for the other unsupported strategies to DEFAULT , the Java program will still throw the exception because Java program is expecting a particular response format(HUFFMAN, RLE etc) . For compression level 0 (DEFAULT) we still have to analyse.

chenhealth1234 commented 1 year ago

Dear ,

Appreciate a lot for your support. now it is ok, we will do further testing as customer's request, if any question, we will give you update ASAP. Thanks again.