Commit e7e4aa34 authored by Julien Lacoste's avatar Julien Lacoste
Browse files

Merge branch 'wip/julien.lacoste/downloaderror' into 'master'

Java bindings : Upload/download error info + VolumeDataPage short data handling

See merge request !464
parents e86b6503 a93cf4ef
Pipeline #67501 passed with stages
in 21 minutes and 10 seconds
......@@ -18,6 +18,7 @@ set(JAVA_SOURCE_FILES
java/src/org/opengroup/openvds/BufferUtils.java
java/src/org/opengroup/openvds/Cleaner.java
java/src/org/opengroup/openvds/CompressionMethod.java
java/src/org/opengroup/openvds/ConnectionErrorInfo.java
java/src/org/opengroup/openvds/DimensionsND.java
java/src/org/opengroup/openvds/experimental/VariousJavaTests.java
java/src/org/opengroup/openvds/GoogleOpenOptions.java
......@@ -97,7 +98,9 @@ set(JAVA_TEST_SOURCES_FILES
java/test/org/opengroup/openvds/CreateVDSTest.java
java/test/org/opengroup/openvds/WriteDataTest.java
java/test/org/opengroup/openvds/MetaDataContainerTest.java
java/test/org/opengroup/openvds/PageAccessorTest.java
java/test/org/opengroup/openvds/PageAccessorByteTest.java
java/test/org/opengroup/openvds/PageAccessorFloatTest.java
java/test/org/opengroup/openvds/PageAccessorShortTest.java
)
add_jar(openvds-java-test
......
......@@ -285,6 +285,23 @@ JNIEXPORT void JNICALL Java_org_opengroup_openvds_MetadataContainer_cpSetMetadat
CATCH_EXCEPTIONS_FOR_JAVA;
}
/*
* Class: org_opengroup_openvds_MetadataContainer
* Method: cpSetMetadataBLOB
* Signature: (JLjava/lang/String;Ljava/lang/String;[B)V
*/
JNIEXPORT void JNICALL Java_org_opengroup_openvds_MetadataContainer_cpSetMetadataBLOB
(JNIEnv * env, jclass, jlong handle, jstring category, jstring name, jbyteArray valueArray)
{
try {
int valueSize = env->GetArrayLength(valueArray);
jbyte *src = env->GetByteArrayElements(valueArray, NULL);
GetAccess( handle )->SetMetadataBLOB(JStringToString( env, category ).c_str(), JStringToString( env, name ).c_str(), src, valueSize);
env->ReleaseByteArrayElements(valueArray, src, 0);
}
CATCH_EXCEPTIONS_FOR_JAVA;
}
#ifdef __cplusplus
}
#endif
......@@ -443,6 +443,27 @@ extern "C" {
return NULL;
}
/*
* Class: org_opengroup_openvds_MetadataReadAccess
* Method: cpGetMetadataBLOB
* Signature: (JLjava/lang/String;Ljava/lang/String;)[B
*/
JNIEXPORT jbyteArray JNICALL Java_org_opengroup_openvds_MetadataReadAccess_cpGetMetadataBLOB
(JNIEnv *env, jclass, jlong handle, jstring category, jstring name)
{
try {
// read blob
std::vector<int8_t> blob;
GetAccess( handle )->GetMetadataBLOB(JStringToString( env, category ).c_str(), JStringToString( env, name ).c_str(), blob );
// convert to array
const char* blobArray = reinterpret_cast<const char *>(blob.data());
return NewJByteArray(env, blobArray, blob.size());
}
CATCH_EXCEPTIONS_FOR_JAVA;
return NULL;
}
/*
* Class: org_opengroup_openvds_MetadataReadAccess
* Method: cpGetMetadataKeys
......
......@@ -583,6 +583,67 @@ JNIEXPORT jint JNICALL Java_org_opengroup_openvds_VolumeDataAccessManager_cpGetC
return 0;
}
/*
* Class: org_opengroup_openvds_VolumeDataAccessManager
* Method: cpGetCurrentUploadErrorInfo
* Signature: (JLorg/opengroup/openvds/ErrorInfo;)V
*/
JNIEXPORT void JNICALL Java_org_opengroup_openvds_VolumeDataAccessManager_cpGetCurrentUploadErrorInfo
(JNIEnv * env, jclass, jlong handle, jobject errorObj)
{
try {
const char *pObjectID = nullptr;
const char *pErrorString = nullptr;
int32_t errorCode = 0;
GetManager(handle)->GetCurrentUploadError(&pObjectID, &errorCode, &pErrorString);
// Get the class of the given error object
jclass clazz = env->GetObjectClass(errorObj);
// Get Field references
jfieldID paramCode = env->GetFieldID(clazz, "errorCode", "I");
jfieldID paramMessage = env->GetFieldID(clazz, "errorMessage", "Ljava/lang/String;");
jfieldID paramID = env->GetFieldID(clazz, "objectID", "Ljava/lang/String;");
// Set fields for object
jstring strMsg = NewJString(env, pErrorString);
jstring strID = NewJString(env, pObjectID);
env->SetIntField(errorObj, paramCode, errorCode);
env->SetObjectField(errorObj, paramMessage, strMsg);
env->SetObjectField(errorObj, paramID, strID);
}
CATCH_EXCEPTIONS_FOR_JAVA;
}
/*
* Class: org_opengroup_openvds_VolumeDataAccessManager
* Method: cpGetCurrentDownloadErrorInfo
* Signature: (JLorg/opengroup/openvds/ErrorInfo;)V
*/
JNIEXPORT void JNICALL Java_org_opengroup_openvds_VolumeDataAccessManager_cpGetCurrentDownloadErrorInfo
(JNIEnv * env, jclass, jlong handle, jobject errorObj)
{
try {
const char *pErrorString = nullptr;
int32_t errorCode = 0;
GetManager(handle)->GetCurrentDownloadError(&errorCode, &pErrorString);
// Get the class of the given error object
jclass clazz = env->GetObjectClass(errorObj);
// Get Field references
jfieldID paramCode = env->GetFieldID(clazz, "errorCode", "I");
jfieldID paramMessage = env->GetFieldID(clazz, "errorMessage", "Ljava/lang/String;");
// Set fields for object
env->SetIntField(errorObj, paramCode, errorCode);
jstring strMsg = NewJString(env, pErrorString);
env->SetObjectField(errorObj, paramMessage, strMsg);
}
CATCH_EXCEPTIONS_FOR_JAVA;
}
#ifdef __cplusplus
}
#endif
......@@ -242,6 +242,47 @@ extern "C" {
CATCH_EXCEPTIONS_FOR_JAVA;
}
/*
* Class: org_opengroup_openvds_VolumeDataPage
* Method: cpGetShortBuffer
* Signature: (J[II)[S
*/
JNIEXPORT jshortArray JNICALL Java_org_opengroup_openvds_VolumeDataPage_cpGetShortBuffer
(JNIEnv * env, jclass, jlong handle, jintArray pitchParam, jint lod)
{
try {
int pitch[OpenVDS::Dimensionality_Max];
OpenVDS::VolumeDataPage* page = GetVolumePage(handle);
const short* readData = (const short*)page->GetBuffer(pitch);
env->SetIntArrayRegion(pitchParam, 0, OpenVDS::Dimensionality_Max, (jint *)pitch);
int nbElem = GetBufferAllocatedSize(page);
return NewJShortArray(env, readData, nbElem);
}
CATCH_EXCEPTIONS_FOR_JAVA;
return NULL;
}
/*
* Class: org_opengroup_openvds_VolumeDataPage
* Method: cpSetShortBuffer
* Signature: (J[S)V
*/
JNIEXPORT void JNICALL Java_org_opengroup_openvds_VolumeDataPage_cpSetShortBuffer
(JNIEnv * env, jclass, jlong handle, jshortArray values)
{
try {
OpenVDS::VolumeDataPage * page = GetVolumePage(handle);
int pitch[OpenVDS::Dimensionality_Max];
short* pageBuffer = (short*)page->GetWritableBuffer(pitch);
int valueSize = env->GetArrayLength(values);
jshort *src = env->GetShortArrayElements(values, NULL);
std::memcpy(pageBuffer, src, valueSize * sizeof (short));
env->ReleaseShortArrayElements(values, src, 0);
}
CATCH_EXCEPTIONS_FOR_JAVA;
}
#ifdef __cplusplus
}
#endif
......@@ -157,7 +157,7 @@ public class CreateVDS {
true, // is renderable
false, // allow lossy compression
false, // use zip for lossless compresion
true, // use no value
false, // use no value
-999.25f, // no value
scaleOffset[0], // integer scale
scaleOffset[1]); // integer offset
......
......@@ -27,6 +27,14 @@ import java.nio.ShortBuffer;
import java.util.Objects;
public abstract class BufferUtils {
/**
* @param array Th array to be copied into the new buffer
* @return A direct buffer copy of the given array
*/
public static ByteBuffer toBuffer(byte[] array) {
return (ByteBuffer) createByteBuffer(array.length).put(array).clear();
}
/**
* @param array Th array to be copied into the new buffer
* @return A direct buffer copy of the given array
......
package org.opengroup.openvds;
/**
* Simple class holding information on Upload/Download error
*/
public class ConnectionErrorInfo {
private int errorCode = -1;
private String errorMessage;
private String objectID;
public ConnectionErrorInfo() { }
public ConnectionErrorInfo(int code, String msg, String id) {
errorCode = code;
errorMessage = msg;
objectID = id;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public String getObjectID() {
return objectID;
}
public void setObjectID(String objectID) {
this.objectID = objectID;
}
}
......@@ -17,8 +17,7 @@
package org.opengroup.openvds;
import java.util.HashMap;
import java.util.Map;
import java.nio.ByteBuffer;
public class MetadataContainer extends MetadataReadAccess {
......@@ -52,6 +51,8 @@ public class MetadataContainer extends MetadataReadAccess {
private static native void cpSetMetadataString(long handle, String category, String name, String value);
private static native void cpSetMetadataBLOB(long handle, String category, String name, byte[] blobValues);
/**
* Constructor around existing JNI object
* @param handle jni pointer to existing container
......@@ -204,6 +205,32 @@ public class MetadataContainer extends MetadataReadAccess {
cpSetMetadataString(_handle, category, name, value);
}
/**
* set Meta data blob using a byte array
* @param category
* @param name
* @param blobValues
*/
public void setMetadataBLOB(String category, String name, byte[] blobValues) {
if (blobValues == null) {
throw new IllegalArgumentException("Blob values array is null.");
}
cpSetMetadataBLOB(_handle, category, name, blobValues);
}
/**
* set Meta data blob using a byte array
* @param category
* @param name
* @param blobValues
*/
public void setMetadataBLOB(String category, String name, ByteBuffer blobValues) {
if (blobValues == null) {
throw new IllegalArgumentException("Blob values buffer is null.");
}
cpSetMetadataBLOB(_handle, category, name, blobValues.array());
}
private void checkArrayArgument(int[] array, int expectedSize) {
if (array == null || array.length != expectedSize) {
......
......@@ -17,6 +17,8 @@
package org.opengroup.openvds;
import java.nio.ByteBuffer;
public class MetadataReadAccess extends JniPointerWithoutDeletion {
private static native boolean cpIsMetadataIntAvailable(long handle, String category, String name);
......@@ -73,6 +75,8 @@ public class MetadataReadAccess extends JniPointerWithoutDeletion {
private static native String cpGetMetadataString(long handle, String category, String name);
private static native byte[] cpGetMetadataBLOB(long handle, String category, String name);
private static native MetadataKey[] cpGetMetadataKeys(long handle);
public MetadataReadAccess(long handle) {
......@@ -337,6 +341,27 @@ public class MetadataReadAccess extends JniPointerWithoutDeletion {
return cpGetMetadataString(_handle, category, name);
}
/**
* get Metadata blob as byte array
* @param category
* @param name
* @return
*/
public byte[] getMetadataBLOB(String category, String name) {
return cpGetMetadataBLOB(_handle, category, name);
}
/**
* get Metadata blob as byte buffer
* @param category
* @param name
* @return
*/
public ByteBuffer getMetadataBLOBAsBuffer(String category, String name) {
byte[] blobArray = cpGetMetadataBLOB(_handle, category, name);
return ByteBuffer.wrap(blobArray);
}
/**
* @return an array of metadata keys
*/
......
......@@ -147,6 +147,10 @@ public class VolumeDataAccessManager extends JniPointerWithoutDeletion {
private static native int cpGetCurrentUploadErrorCode(long handle);
private static native void cpGetCurrentUploadErrorInfo(long handle, ConnectionErrorInfo error);
private static native void cpGetCurrentDownloadErrorInfo(long handle, ConnectionErrorInfo error);
public VolumeDataAccessManager(long handle) {
super(handle);
}
......@@ -771,4 +775,22 @@ public class VolumeDataAccessManager extends JniPointerWithoutDeletion {
public int getCurrentUploadErrorCode() {
return cpGetCurrentUploadErrorCode(_handle);
}
/**
* @return current upload error information (code and message in a simple class)
*/
public ConnectionErrorInfo getCurrentUploadErrorInfo() {
ConnectionErrorInfo connectionErrorInfo = new ConnectionErrorInfo();
cpGetCurrentUploadErrorInfo(_handle, connectionErrorInfo);
return connectionErrorInfo;
}
/**
* @return current upload error information (code and message in a simple class)
*/
public ConnectionErrorInfo getCurrentDownloadErrorInfo() {
ConnectionErrorInfo connectionErrorInfo = new ConnectionErrorInfo();
cpGetCurrentDownloadErrorInfo(_handle, connectionErrorInfo);
return connectionErrorInfo;
}
}
......@@ -41,6 +41,11 @@ public class VolumeDataPage extends JniPointerWithoutDeletion {
private static native void cpSetDoubleBuffer(long handle, double[] buffer);
private static native short[] cpGetShortBuffer(long handle, int[] pitch, int lod);
private static native void cpSetShortBuffer(long handle, short[] buffer);
private final int dimensionality;
private final int lod;
......@@ -144,6 +149,26 @@ public class VolumeDataPage extends JniPointerWithoutDeletion {
cpSetFloatBuffer(_handle, buffer);
}
/**
* Read short array of page
* @param pitch will receive pitch values for this page
* @return the short array of page data
*/
public short[] readShortBuffer(int[] pitch) {
checkDimParamArray(pitch, "Wrong pitch array parameter size, expected ");
return cpGetShortBuffer(_handle, pitch, lod);
}
/**
* Set short array int page
* @param buffer values to set. Size must match page sample size
* @param pitch chunk pitch (got by a read)
*/
public void writeShortBuffer(short[] buffer, int[] pitch) {
checkBufferSize(buffer, pitch, dimensionality, lod);
cpSetShortBuffer(_handle, buffer);
}
/**
* Read double array of page
* @param pitch will receive pitch values for this page
......@@ -192,6 +217,13 @@ public class VolumeDataPage extends JniPointerWithoutDeletion {
checkBufferSize(buffer.length, pitch, dimensionality, lod);
}
private void checkBufferSize(short[] buffer, int[] pitch, int dim, int lod) {
if (buffer == null) {
throw new IllegalArgumentException("Wrong buffer size, got NULL");
}
checkBufferSize(buffer.length, pitch, dimensionality, lod);
}
private void checkBufferSize(int sizeInputBuffer, int[] pitch, int dim, int lod) {
int pageBufferSize = getAllocatedBufferSize();
if (sizeInputBuffer != pageBufferSize) {
......
......@@ -17,11 +17,15 @@
package org.opengroup.openvds;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.Random;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
......@@ -308,4 +312,66 @@ public class MetaDataContainerTest {
}
}
@Test
public void testMetaDataBlob() {
MetadataContainer metaData = new MetadataContainer();
byte[] blobArray = new byte[3200];
Random rand = new Random(System.currentTimeMillis());
rand.nextBytes(blobArray);
metaData.setMetadataBLOB("Blob data", "blob array", blobArray);
Assert.assertTrue(metaData.isMetadataBLOBAvailable("Blob data", "blob array"));
byte[] metadataBLOBArray = metaData.getMetadataBLOB("Blob data", "blob array");
Assert.assertEquals(blobArray, metadataBLOBArray);
}
@Test
public void testMetaDataBlobBuffer() {
MetadataContainer metaData = new MetadataContainer();
byte[] blobArray = new byte[3200];
Random rand = new Random(System.currentTimeMillis());
rand.nextBytes(blobArray);
ByteBuffer blobBuffer = ByteBuffer.wrap(blobArray);
metaData.setMetadataBLOB("Blob data", "blob array", blobBuffer);
Assert.assertTrue(metaData.isMetadataBLOBAvailable("Blob data", "blob array"));
ByteBuffer metadataBLOBBuffer = metaData.getMetadataBLOBAsBuffer("Blob data", "blob array");
// compares buffer
Assert.assertTrue(metadataBLOBBuffer.equals(blobBuffer));
}
@Test
public void testMetaDataBlobFloatBuffer() {
MetadataContainer metaData = new MetadataContainer();
// put floats in a byte buffer
float[] blobFloatArray = new float[2000];
Random rand = new Random(System.currentTimeMillis());
for (int i = 0 ; i < blobFloatArray.length ; ++i) {
blobFloatArray[i] = rand.nextFloat();
}
ByteBuffer byteBuffer = ByteBuffer.allocate(Float.BYTES * blobFloatArray.length);
byteBuffer.asFloatBuffer().put(blobFloatArray);
// writes them
metaData.setMetadataBLOB("Blob data", "blob array", byteBuffer);
// reread and compare
Assert.assertTrue(metaData.isMetadataBLOBAvailable("Blob data", "blob array"));
ByteBuffer metadataBLOBBuffer = metaData.getMetadataBLOBAsBuffer("Blob data", "blob array");
FloatBuffer metaDataFB = metadataBLOBBuffer.asFloatBuffer();
int size = metaDataFB.remaining();
float[] readFloats = new float[size];
metaDataFB.get(readFloats);
// compares buffer
Assert.assertEquals(blobFloatArray, readFloats);
}
}
/*
* Copyright 2021 The Open Group
* Copyright 2021 INT, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.opengroup.openvds;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.File;
import static org.testng.Assert.fail;
public class PageAccessorByteTest {
private static String TEMP_FILE_NAME_VOL_INDEX = "volIndexer";
private static String TEMP_FILE_NAME_COPY = "vdsCopyByte";
public String url;
public VolumeDataLayoutDescriptor ld;
public VolumeDataAxisDescriptor[] vda;
public VolumeDataChannelDescriptor[] vdc;
public MetadataReadAccess md;
public MemoryVdsGenerator vds;
public MetadataContainer metadataContainer;
private String tempVolIndexerFileName;
private String tempVdsCopyFileName;
@BeforeClass
public void init() {
vds = new MemoryVdsGenerator(200, 200, 200, VolumeDataChannelDescriptor.Format.FORMAT_U8);
url = "inmemory://create_test";
VolumeDataLayout volumeDataLayout = vds.getLayout();
int nbChannel = volumeDataLayout.getChannelCount();
VolumeDataAccessManager accessManager = vds.getAccessManager();
for (VolumeDataLayoutDescriptor.LODLevels l : VolumeDataLayoutDescriptor.LODLevels.values()) {
for (int channel = 0; channel < nbChannel; channel++) {
for (DimensionsND dimGroup : DimensionsND.values()) {
VDSProduceStatus vdsProduceStatus = accessManager.getVDSProduceStatus(dimGroup, l.ordinal(), channel);
}
}