blob: 2b8338dd5f44f4a2cddf8ce23b618c3fba5f7ef3 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include <common.h>
#define TRANSTABLEITEMLEN 3
#define FRAMESITEMLEN 4
/******************************************************************************
** Generally-useful functions for JNI programming.
*****************************************************************************/
/**
* Throws a RuntimeException, with either an explicit message or the message
* corresponding to the current system error value.
*/
void throw(JNIEnv* env, const char* msg) {
if (msg == NULL)
msg = strerror(errno);
jclass xklass = (*env)->FindClass(env, "java/lang/RuntimeException");
(*env)->ThrowNew(env, xklass, msg);
}
void* addr_from_java(jlong addr) {
// This assert fails in a variety of ways on 32-bit systems.
// It is impossible to predict whether native code that converts
// pointers to longs will sign-extend or zero-extend the addresses.
//assert(addr == (uintptr_t)addr, "must not be odd high bits");
return (void*) (uintptr_t) addr;
}
jlong addr_to_java(void* p) {
assert(p == (void*) (uintptr_t) p);
return (long) (uintptr_t) p;
}
void destructNValInfo(struct NValueInfo *nvinfo) {
if (NULL != nvinfo) {
if (NULL != nvinfo->transtable) {
free(nvinfo->transtable);
}
if (NULL != nvinfo->memfuncs) {
free(nvinfo->memfuncs);
}
if (NULL != nvinfo->frames) {
free(nvinfo->frames);
}
free(nvinfo);
}
}
struct NValueInfo *constructNValInfo(JNIEnv* env, jobject vinfoobj) {
struct NValueInfo *ret = NULL;
static int inited = 0;
static jclass vinfocls = NULL, dutenum = NULL;
static jfieldID handler_fid = NULL, transtable_fid = NULL, memfuncs_fid = NULL;
static jfieldID frames_fid = NULL, dtype_fid = NULL;
static jmethodID getval_mtd = NULL;
if (NULL == vinfoobj) {
return NULL;
}
if (0 == inited) {
inited = 1;
vinfocls = (*env)->FindClass(env, "org/apache/mnemonic/service/computing/ValueInfo");
dutenum = (*env)->FindClass(env, "org/apache/mnemonic/DurableType");
if (NULL != vinfocls && NULL != dutenum) {
handler_fid = (*env)->GetFieldID(env, vinfocls, "handler", "J");
transtable_fid = (*env)->GetFieldID(env, vinfocls, "transtable", "[[J");
memfuncs_fid = (*env)->GetFieldID(env, vinfocls, "memfuncs", "[J");
frames_fid = (*env)->GetFieldID(env, vinfocls, "frames", "[[J");
dtype_fid = (*env)->GetFieldID(env, vinfocls, "dtype",
"Lorg/apache/mnemonic/DurableType;");
getval_mtd = (*env)->GetMethodID(env, dutenum, "getValue", "()I");
} else {
return NULL;
}
}
if (NULL == vinfocls || NULL == handler_fid ||
NULL == transtable_fid || NULL == memfuncs_fid || NULL == frames_fid ||
NULL == dtype_fid || NULL == getval_mtd) {
return NULL;
}
ret = (struct NValueInfo *)calloc(1, sizeof(struct NValueInfo));
if (NULL != ret) {
jlongArray itmarr;
jlong *itms;
jsize itmarrlen, i;
ret->handler = (*env)->GetLongField(env, vinfoobj, handler_fid);
jobject dutobj = (*env)->GetObjectField(env, vinfoobj, dtype_fid);
ret->dtype = (*env)->CallIntMethod(env, dutobj, getval_mtd);
jobjectArray tbarr = (*env)->GetObjectField(env, vinfoobj, transtable_fid);
jsize tbarrlen = 0;
ret->transtablesz = 0;
if (NULL != tbarr) {
tbarrlen = (*env)->GetArrayLength(env, tbarr);
}
if (tbarrlen > 0){
ret->transtable = (struct transitem *)calloc(
tbarrlen, sizeof(struct transitem));
if (NULL != ret->transtable) {
ret->transtablesz = tbarrlen;
for (i = 0; i < tbarrlen; ++i) {
itmarr = (jlongArray)((*env)->GetObjectArrayElement(env, tbarr, i));
itmarrlen = (*env)->GetArrayLength(env, itmarr);
if (NULL != itmarr && TRANSTABLEITEMLEN == itmarrlen) {
itms = (*env)->GetLongArrayElements(env, itmarr, NULL);
(ret->transtable + i)->hdlbase = itms[0];
(ret->transtable + i)->size = itms[1];
(ret->transtable + i)->base = addr_from_java(itms[2]);
(*env)->ReleaseLongArrayElements(env, itmarr, itms, JNI_ABORT);
} else {
return NULL;
}
}
} else {
destructNValInfo(ret);
return NULL;
}
}
jobjectArray mfarr = (*env)->GetObjectField(env, vinfoobj, memfuncs_fid);
jsize mfarrlen = 0;
ret->memfuncssz = 0;
if (NULL != mfarr) {
mfarrlen = (*env)->GetArrayLength(env, mfarr);
}
if (mfarrlen > 0){
ret->memfuncs = (void* *)calloc(
mfarrlen, sizeof(jlong));
if (NULL != ret->memfuncs) {
ret->memfuncssz = mfarrlen;
itms = (*env)->GetLongArrayElements(env, mfarr, NULL);
memcpy(ret->memfuncs, itms, mfarrlen * sizeof(jlong));
(*env)->ReleaseLongArrayElements(env, mfarr, itms, JNI_ABORT);
} else {
destructNValInfo(ret);
return NULL;
}
}
jobjectArray fmarr = (*env)->GetObjectField(env, vinfoobj, frames_fid);
jsize fmarrlen = (*env)->GetArrayLength(env, fmarr);
if (NULL != fmarr && fmarrlen > 0){
ret->frames = (struct frameitem *)calloc(
fmarrlen, sizeof(struct frameitem));
if (NULL != ret->frames) {
ret->framessz = fmarrlen;
for (i = 0; i < fmarrlen; ++i) {
itmarr = (jlongArray)((*env)->GetObjectArrayElement(env, fmarr, i));
itmarrlen = (*env)->GetArrayLength(env, itmarr);
if (NULL != itmarr && FRAMESITEMLEN == itmarrlen) {
itms = (*env)->GetLongArrayElements(env, itmarr, NULL);
(ret->frames + i)->nextoff = itms[0];
(ret->frames + i)->nextsz = itms[1];
(ret->frames + i)->nlvloff = itms[2];
(ret->frames + i)->nlvlsz = itms[3];
(*env)->ReleaseLongArrayElements(env, itmarr, itms, JNI_ABORT);
} else {
return NULL;
}
}
} else {
destructNValInfo(ret);
return NULL;
}
}
} else {
return NULL;
}
return ret;
}
struct NValueInfo **constructNValueInfos(JNIEnv* env,
jobjectArray vinfos, size_t *sz) {
if (NULL == sz) {
return NULL;
}
size_t idx;
struct NValueInfo **ret = NULL;
struct NValueInfo *curnvi = NULL;
jobject curviobj;
*sz = (*env)->GetArrayLength(env, vinfos);
if (0 >= *sz) {
return NULL;
}
ret = (struct NValueInfo **)calloc(*sz, sizeof(struct NValueInfo*));
if (NULL == ret) {
return NULL;
}
for(idx = 0; idx < *sz; ++idx) {
curviobj = (*env)->GetObjectArrayElement(env, vinfos, idx);
if (NULL == curviobj) {
continue;
}
curnvi = constructNValInfo(env, curviobj);
if (NULL == curnvi) {
destructNValueInfos(ret, *sz);
return NULL;
}
*(ret + idx) = curnvi;
}
return ret;
}
void destructNValueInfos(struct NValueInfo **nvalinfos, size_t sz) {
size_t idx;
if (NULL != nvalinfos) {
for(idx = 0; idx < sz; ++idx) {
destructNValInfo(*(nvalinfos + idx));
}
free(nvalinfos);
}
}
void printNValueInfos(struct NValueInfo **nvalinfos, size_t sz) {
size_t idx, i;
struct NValueInfo *itm;
struct transitem *ttitm;
struct frameitem *fitm;
printf("\n--- Native ValueInfo List, Addr:%p, Size: %zu ---\n", nvalinfos, sz);
if (NULL != nvalinfos) {
for(idx = 0; idx < sz; ++idx) {
itm = *(nvalinfos + idx);
printf("** Item %2zu, Addr:%p ** \n", idx, itm);
if (NULL != itm) {
printf("Handler:%ld, DType Value:%d\n", itm->handler, itm->dtype);
printf(">> TransTable: Addr:%p, Size:%zu <<\n", itm->transtable, itm->transtablesz);
if (NULL != itm->transtable && itm->transtablesz > 0) {
for (i = 0; i < itm->transtablesz; ++i) {
ttitm = (itm->transtable + i);
printf("%2zu)", i);
if (NULL != ttitm) {
printf("hdlbase:%ld, size:%ld, base:%p\n",
ttitm->hdlbase, ttitm->size, ttitm->base);
} else {
printf("NULL\n");
}
}
} else {
printf("NULL\n");
}
printf(">> Frames: Addr:%p, Size:%zu <<\n", itm->frames, itm->framessz);
if (NULL != itm->frames && itm->framessz > 0) {
for (i = 0; i < itm->framessz; ++i) {
fitm = (itm->frames + i);
printf("%2zu)", i);
if (NULL != fitm) {
printf("nextoff:%ld, nextsz:%ld, nlvloff:%ld, nlvlsz:%ld\n",
fitm->nextoff, fitm->nextsz, fitm->nlvloff, fitm->nlvlsz);
} else {
printf("NULL\n");
}
}
} else {
printf("NULL\n");
}
} else {
printf("NULL\n");
}
}
} else {
printf("NULL\n");
}
printf("------------------------\n");
}
jlongArray constructJLongArray(JNIEnv* env, long arr[], size_t sz) {
jlongArray ret = (*env)->NewLongArray(env, sz);
if (NULL == ret) {
return NULL;
}
(*env)->SetLongArrayRegion(env, ret, 0, sz, arr);
return ret;
}
inline void *to_e(JNIEnv* env, struct NValueInfo *nvinfo, long p) {
size_t i;
struct transitem * ti;
if (NULL != nvinfo && NULL != nvinfo->transtable) {
for (i = 0; i < nvinfo->transtablesz; ++i) {
ti = nvinfo->transtable + i;
if (p >= ti->hdlbase && p < ti->size) {
return ti->base + p;
}
}
throw(env, "No item found in Translate Table.");
} else {
return addr_from_java(p);
}
return NULL;
}
inline long to_p(JNIEnv* env, struct NValueInfo *nvinfo, void *e) {
size_t i;
struct transitem * ti;
if (NULL != nvinfo && NULL != nvinfo->transtable) {
for (i = 0; i < nvinfo->transtablesz; ++i) {
ti = nvinfo->transtable + i;
if (e >= ti->base && e < ti->base + ti->size) {
return e - ti->base;
}
}
throw(env, "No item found in Translate Table.");
} else {
return addr_to_java(e);
}
return -1L;
}
void iterTensor(JNIEnv* env, struct NValueInfo *nvinfo,
size_t dims[], long *itmaddrs[], long *(* const nxtfitmaddrs)[],
long (* const pendings)[], long hdls[],
size_t dimidx, valueHandler valhandler) {
if (++dimidx >= nvinfo->framessz) {
return;
}
long *iatmp;
long curoff = (nvinfo->frames + dimidx)->nextoff;
long curnloff = (nvinfo->frames + dimidx)->nlvloff;
long curnlsz = (nvinfo->frames + dimidx)->nlvlsz;
void *addr = NULL;
if (dimidx < nvinfo->framessz - 1) {
iatmp = itmaddrs[dimidx];
while (1) {
(*pendings)[dimidx] = 0L;
while(0L != hdls[dimidx]) {
itmaddrs[dimidx + 1] = (long*)(to_e(env, nvinfo, hdls[dimidx]) + curnloff);
hdls[dimidx + 1] = *itmaddrs[dimidx + 1];
(*nxtfitmaddrs)[dimidx] = (long*)(to_e(env, nvinfo, hdls[dimidx]) + curoff);
iterTensor(env, nvinfo, dims, itmaddrs, nxtfitmaddrs, pendings, hdls, dimidx, valhandler);
itmaddrs[dimidx] = (*nxtfitmaddrs)[dimidx];
hdls[dimidx] = *itmaddrs[dimidx];
++dims[dimidx];
}
dims[dimidx] = 0;
if (0L == (*pendings)[dimidx]) {
break;
}
itmaddrs[dimidx] = iatmp;
hdls[dimidx] = *iatmp;
}
} else {
if (-1L != curoff) {
iatmp = itmaddrs[dimidx];
while (1) {
(*pendings)[dimidx] = 0L;
while(0L != hdls[dimidx]) {
addr = to_e(env, nvinfo, hdls[dimidx]) + curnloff;
(*nxtfitmaddrs)[dimidx] = (long*)(to_e(env, nvinfo, hdls[dimidx]) + curoff);
valhandler(env, dims, dimidx, itmaddrs, nxtfitmaddrs, pendings, addr, curnlsz, nvinfo->dtype);
itmaddrs[dimidx] = (*nxtfitmaddrs)[dimidx];
hdls[dimidx] = *itmaddrs[dimidx];
++dims[dimidx];
}
dims[dimidx] = 0;
if (0L == (*pendings)[dimidx]) {
break;
}
itmaddrs[dimidx] = iatmp;
hdls[dimidx] = *iatmp;
}
} else {
addr = to_e(env, nvinfo, hdls[dimidx]) + curnloff;
valhandler(env, dims, dimidx - 1, itmaddrs, nxtfitmaddrs, pendings, addr, curnlsz, nvinfo->dtype);
}
}
}
long handleValueInfo(JNIEnv* env, struct NValueInfo *nvinfo, valueHandler valhandler) {
if (NULL == nvinfo->frames || 0 >= nvinfo->framessz) {
return 0L;
}
size_t dims[nvinfo->framessz];
long *itmaddrs[nvinfo->framessz];
long *nxtfitmaddrs[nvinfo->framessz];
long pendings[nvinfo->framessz];
long hdls[nvinfo->framessz];
size_t i;
for (i = 0; i < nvinfo->framessz; ++i) {
dims[i] = 0;
itmaddrs[i] = NULL;
nxtfitmaddrs[i] = NULL;
pendings[i] = 0L;
hdls[i] = 0L;
}
hdls[0] = nvinfo->handler;
itmaddrs[0] = &nvinfo->handler;
iterTensor(env, nvinfo, dims, itmaddrs, &nxtfitmaddrs, &pendings, hdls, -1, valhandler);
return nvinfo->handler;
}
void vectorIterTensor(JNIEnv* env, struct NValueInfo *nvinfo,
size_t dims[], long *itmaddrs[], long *(* const nxtfitmaddrs)[],
long (* const pendings)[], long hdls[],
size_t dimidx, vecValueHandler valhandler, void *chkaddr, long chksize, long *vposition, long *vcount) {
if (++dimidx >= nvinfo->framessz) {
return;
}
long *iatmp;
long curoff = (nvinfo->frames + dimidx)->nextoff;
long curnloff = (nvinfo->frames + dimidx)->nlvloff;
long curnlsz = (nvinfo->frames + dimidx)->nlvlsz;
void *addr = NULL;
if (dimidx < nvinfo->framessz - 1) {
iatmp = itmaddrs[dimidx];
while (1) {
(*pendings)[dimidx] = 0L;
while(0L != hdls[dimidx]) {
itmaddrs[dimidx + 1] = (long*)(to_e(env, nvinfo, hdls[dimidx]) + curnloff);
hdls[dimidx + 1] = *itmaddrs[dimidx + 1];
(*nxtfitmaddrs)[dimidx] = (long*)(to_e(env, nvinfo, hdls[dimidx]) + curoff);
vectorIterTensor(env, nvinfo, dims, itmaddrs, nxtfitmaddrs, pendings, hdls, dimidx, valhandler, chkaddr, chksize, vposition, vcount);
itmaddrs[dimidx] = (*nxtfitmaddrs)[dimidx];
hdls[dimidx] = *itmaddrs[dimidx];
++dims[dimidx];
}
dims[dimidx] = 0;
if (0L == (*pendings)[dimidx]) {
break;
}
itmaddrs[dimidx] = iatmp;
hdls[dimidx] = *iatmp;
}
} else {
if (-1L != curoff) {
iatmp = itmaddrs[dimidx];
while (1) {
(*pendings)[dimidx] = 0L;
while(0L != hdls[dimidx]) {
addr = to_e(env, nvinfo, hdls[dimidx]) + curnloff;
(*nxtfitmaddrs)[dimidx] = (long*)(to_e(env, nvinfo, hdls[dimidx]) + curoff);
valhandler(env, dims, dimidx, itmaddrs, nxtfitmaddrs, pendings, addr, curnlsz, nvinfo->dtype, chkaddr, chksize, vposition, vcount);
itmaddrs[dimidx] = (*nxtfitmaddrs)[dimidx];
hdls[dimidx] = *itmaddrs[dimidx];
++dims[dimidx];
}
dims[dimidx] = 0;
if (0L == (*pendings)[dimidx]) {
break;
}
itmaddrs[dimidx] = iatmp;
hdls[dimidx] = *iatmp;
}
} else {
addr = to_e(env, nvinfo, hdls[dimidx]) + curnloff;
valhandler(env, dims, dimidx - 1, itmaddrs, nxtfitmaddrs, pendings, addr, curnlsz, nvinfo->dtype, chkaddr, chksize, vposition, vcount);
}
}
}
long handleVectorInfo(JNIEnv* env, struct NValueInfo *nvinfo, vecValueHandler valhandler, long dc_handler, long dc_size, long* count) {
if (NULL == nvinfo->frames || 0 >= nvinfo->framessz) {
return 0L;
}
void *chk_addr = to_e(env, nvinfo, dc_handler);
size_t dims[nvinfo->framessz];
long *itmaddrs[nvinfo->framessz];
long *nxtfitmaddrs[nvinfo->framessz];
long pendings[nvinfo->framessz];
long hdls[nvinfo->framessz];
long position = 0;
size_t i;
for (i = 0; i < nvinfo->framessz; ++i) {
dims[i] = 0;
itmaddrs[i] = NULL;
nxtfitmaddrs[i] = NULL;
pendings[i] = 0L;
hdls[i] = 0L;
}
hdls[0] = nvinfo->handler;
itmaddrs[0] = &nvinfo->handler;
vectorIterTensor(env, nvinfo, dims, itmaddrs, &nxtfitmaddrs, &pendings, hdls, -1, valhandler, chk_addr, dc_size, &position, count);
return nvinfo->handler;
}