blob: 9935e458a5be11191ed27f31b1cdc7bba5c147f7 [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 "org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl.h"
#include "libpmem.h"
static PMPool *g_pmpool_arr = NULL;
static size_t g_pmpool_count = 0;
static pthread_rwlock_t g_pmp_rwlock = PTHREAD_RWLOCK_INITIALIZER;
/******************************************************************************
** JNI implementations
*****************************************************************************/
JNIEXPORT
jlong JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_nallocate(JNIEnv* env,
jobject this, jlong id, jlong size, jboolean initzero) {
PMPool *pool;
jlong ret = 0L;
void *p;
pthread_rwlock_rdlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
p = prealloc(pool, NULL, size, initzero ? 1 : 0);
if (NULL != p) {
ret = addr_to_java(p);
}
pthread_rwlock_unlock(&g_pmp_rwlock);
return ret;
}
JNIEXPORT
jlong JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_nreallocate(JNIEnv* env,
jobject this, jlong id, jlong addr, jlong size, jboolean initzero) {
PMPool *pool;
jlong ret = 0L;
void *p;
pthread_rwlock_rdlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
p = addr_from_java(addr);
p = prealloc(pool, p, size, initzero ? 1 : 0);
if (NULL != p) {
ret = addr_to_java(p);
}
pthread_rwlock_unlock(&g_pmp_rwlock);
return ret;
}
JNIEXPORT
void JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_nfree(
JNIEnv* env,
jobject this, jlong id,
jlong addr)
{
PMPool *pool;
void* nativebuf;
pthread_rwlock_rdlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
//fprintf(stderr, "nfree Get Called %ld, %X\n", id, addr);
nativebuf = addr_from_java(addr);
pfree(pool, nativebuf);
pthread_rwlock_unlock(&g_pmp_rwlock);
}
JNIEXPORT
void JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_nsync(
JNIEnv* env,
jobject this, jlong id, jlong addr, jlong len, jboolean autodetect)
{
PMPool *pool;
size_t capa;
void* nativebuf;
void* p = addr_from_java(addr);
if (autodetect) {
if (NULL != p) {
nativebuf = p - PMBHSZ;
pmem_msync(nativebuf, ((PMBHeader *) nativebuf)->size);
} else {
pthread_rwlock_rdlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
capa = pool->capacity;
pmem_msync(pool->base, capa);
pthread_rwlock_unlock(&g_pmp_rwlock);
}
} else {
if (NULL != p && len > 0L) {
pmem_msync(p, len);
}
}
}
JNIEXPORT
void JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_npersist(
JNIEnv* env,
jobject this, jlong id, jlong addr, jlong len, jboolean autodetect)
{
PMPool *pool;
size_t capa;
void* nativebuf;
void* p = addr_from_java(addr);
if (autodetect) {
if (NULL != p) {
nativebuf = p - PMBHSZ;
pmem_persist(nativebuf, ((PMBHeader *) nativebuf)->size);
} else {
pthread_rwlock_rdlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
capa = pool->capacity;
pmem_persist(pool->base, capa);
pthread_rwlock_unlock(&g_pmp_rwlock);
}
} else {
if (NULL != p && len > 0L) {
pmem_persist(p, len);
}
}
}
JNIEXPORT
void JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_nflush(
JNIEnv* env,
jobject this, jlong id, jlong addr, jlong len, jboolean autodetect)
{
PMPool *pool;
size_t capa;
void* nativebuf;
void* p = addr_from_java(addr);
if (autodetect) {
if (NULL != p) {
nativebuf = p - PMBHSZ;
pmem_flush(nativebuf, ((PMBHeader *) nativebuf)->size);
} else {
pthread_rwlock_rdlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
capa = pool->capacity;
pmem_flush(pool->base, capa);
pthread_rwlock_unlock(&g_pmp_rwlock);
}
} else {
if (NULL != p && len > 0L) {
pmem_flush(p, len);
}
}
}
JNIEXPORT
void JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_ndrain(
JNIEnv* env,
jobject this, jlong id)
{
pmem_drain();
}
JNIEXPORT
jlong JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_ncapacity(
JNIEnv* env,
jobject this, jlong id)
{
PMPool *pool;
jlong ret;
pthread_rwlock_rdlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
ret = pool->capacity;
pthread_rwlock_unlock(&g_pmp_rwlock);
return ret;
}
JNIEXPORT
jobject JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_ncreateByteBuffer(
JNIEnv *env, jobject this, jlong id, jlong size) {
PMPool *pool;
jobject ret = NULL;
void* nativebuf = NULL;
pthread_rwlock_rdlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
nativebuf = prealloc(pool, NULL, size, 0);
if (NULL != nativebuf) {
ret = (*env)->NewDirectByteBuffer(env, nativebuf, size);
}
pthread_rwlock_unlock(&g_pmp_rwlock);
return ret;
}
JNIEXPORT
jobject JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_nretrieveByteBuffer(
JNIEnv *env, jobject this, jlong id, jlong addr) {
jobject ret = NULL;
void* p = addr_from_java(addr);
if (NULL != p) {
void* nativebuf = p - PMBHSZ;
ret = (*env)->NewDirectByteBuffer(env, p, ((PMBHeader *) nativebuf)->size - PMBHSZ);
}
return ret;
}
JNIEXPORT
jlong JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_nretrieveSize(JNIEnv *env,
jobject this, jlong id, jlong addr) {
jlong ret = 0L;
void* p = addr_from_java(addr);
if (NULL != p) {
void* nativebuf = p - PMBHSZ;
ret = ((PMBHeader *) nativebuf)->size - PMBHSZ;
// fprintf(stderr, "### nretrieveSize size: %lld, %X ###, header size: %ld \n",
// ((PMBHeader *)nativebuf)->size, nativebuf-b_addr(*(g_pmpool_arr + id)), PMBHSZ);
}
return ret;
}
JNIEXPORT
jlong JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_ngetByteBufferHandler(
JNIEnv *env, jobject this, jlong id, jobject bytebuf) {
// fprintf(stderr, "ngetByteBufferAddress Get Called %X, %X\n", env, bytebuf);
jlong ret = 0L;
if (NULL != bytebuf) {
void* nativebuf = (*env)->GetDirectBufferAddress(env, bytebuf);
// fprintf(stderr, "ngetByteBufferAddress Get Native addr %X\n", nativebuf);
ret = addr_to_java(nativebuf);
}
// fprintf(stderr, "ngetByteBufferAddress returned addr %016lx\n", ret);
return ret;
}
JNIEXPORT
jobject JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_nresizeByteBuffer(
JNIEnv *env, jobject this, jlong id, jobject bytebuf, jlong size) {
PMPool *pool;
jobject ret = NULL;
pthread_rwlock_rdlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
if (NULL != bytebuf) {
void* nativebuf = (*env)->GetDirectBufferAddress(env, bytebuf);
if (nativebuf != NULL) {
nativebuf = prealloc(pool, nativebuf, size, 0);
if (NULL != nativebuf) {
ret = (*env)->NewDirectByteBuffer(env, nativebuf, size);
}
}
}
pthread_rwlock_unlock(&g_pmp_rwlock);
return ret;
}
JNIEXPORT
void JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_ndestroyByteBuffer(
JNIEnv *env, jobject this, jlong id, jobject bytebuf)
{
PMPool *pool;
pthread_rwlock_rdlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
if (NULL != bytebuf) {
void* nativebuf = (*env)->GetDirectBufferAddress(env, bytebuf);
pfree(pool, nativebuf);
}
pthread_rwlock_unlock(&g_pmp_rwlock);
}
JNIEXPORT
void JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_nsetHandler(
JNIEnv *env, jobject this, jlong id, jlong key, jlong value)
{
PMPool *pool;
TOID(struct pmem_root) root;
pthread_rwlock_rdlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
root = POBJ_ROOT(pool->pop, struct pmem_root);
if (key < MAX_HANDLER_STORE_LEN && key >= 0) {
D_RW(root)->hdl_buf[key] = value;
}
pthread_rwlock_unlock(&g_pmp_rwlock);
}
JNIEXPORT
jlong JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_ngetHandler(JNIEnv *env,
jobject this, jlong id, jlong key) {
PMPool *pool;
TOID(struct pmem_root) root;
pthread_rwlock_rdlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
root = POBJ_ROOT(pool->pop, struct pmem_root);
jlong ret = (key < MAX_HANDLER_STORE_LEN && key >= 0) ? D_RO(root)->hdl_buf[key] : 0L;
pthread_rwlock_unlock(&g_pmp_rwlock);
return ret;
}
JNIEXPORT
jlong JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_nhandlerCapacity(
JNIEnv *env, jobject this) {
return MAX_HANDLER_STORE_LEN;
}
JNIEXPORT
jlong JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_ngetBaseAddress(JNIEnv *env,
jobject this, jlong id) {
PMPool *pool;
jlong ret;
pthread_rwlock_rdlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
ret = addr_to_java(pool->base);
pthread_rwlock_unlock(&g_pmp_rwlock);
return ret;
}
JNIEXPORT
jlong JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_ninit(JNIEnv *env,
jclass this, jlong capacity, jstring pathname, jboolean isnew) {
PMPool *pool;
TOID(struct pmem_root) root;
int needcreate;
jlong ret = -1;
PMEMobjpool *pop = NULL;
pthread_rwlock_wrlock(&g_pmp_rwlock);
const char* mpathname = (*env)->GetStringUTFChars(env, pathname, NULL);
if (NULL == mpathname) {
pthread_rwlock_unlock(&g_pmp_rwlock);
throw(env, "Big memory path not specified!");
}
needcreate = access(mpathname, F_OK);
if (isnew && !needcreate) {
if(0 != unlink(mpathname)) {
throw(env, "Failure to delete file to create new one.");
}
needcreate = 1;
}
if (needcreate && capacity < PMEMOBJ_MIN_POOL) {
capacity = PMEMOBJ_MIN_POOL;
}
if (needcreate) {
pop = pmemobj_create(mpathname, POBJ_LAYOUT_NAME(memory_service), capacity, S_IRUSR | S_IWUSR);
} else {
pop = pmemobj_open(mpathname, POBJ_LAYOUT_NAME(memory_service));
}
if (pop == NULL) {
pthread_rwlock_unlock(&g_pmp_rwlock);
throw(env, "Big memory init failure!");
}
(*env)->ReleaseStringUTFChars(env, pathname, mpathname);
g_pmpool_arr = realloc(g_pmpool_arr, (g_pmpool_count + 1) * sizeof(PMPool));
if (NULL != g_pmpool_arr) {
pool = g_pmpool_arr + g_pmpool_count;
pool->pop = pop;
root = POBJ_ROOT(pool->pop, struct pmem_root);
pool->uuid_lo = root.oid.pool_uuid_lo;
pool->base = (void*)pop;
if (needcreate) {
pool->capacity = capacity;
D_RW(root)->capacity = capacity;
} else {
pool->capacity = D_RO(root)->capacity;
}
ret = g_pmpool_count;
++g_pmpool_count;
} else {
pthread_rwlock_unlock(&g_pmp_rwlock);
throw(env, "Big memory init Out of memory!");
}
pthread_rwlock_unlock(&g_pmp_rwlock);
return ret;
}
JNIEXPORT
void JNICALL Java_org_apache_mnemonic_service_memory_internal_PMDKPMemServiceImpl_nclose
(JNIEnv *env, jobject this, jlong id)
{
PMPool *pool;
pthread_rwlock_wrlock(&g_pmp_rwlock);
pool = g_pmpool_arr + id;
if (NULL != pool->pop) {
pmemobj_close(pool->pop);
pool->pop = NULL;
pool->base = NULL;
pool->uuid_lo = 0;
pool->capacity = 0;
}
pthread_rwlock_unlock(&g_pmp_rwlock);
}
__attribute__((destructor)) void fini(void) {
int i;
PMPool *pool;
pthread_rwlock_wrlock(&g_pmp_rwlock);
if (NULL != g_pmpool_arr) {
for (i = 0; i < g_pmpool_count; ++i) {
pool = g_pmpool_arr + i;
if (NULL != pool->pop) {
pmemobj_close(pool->pop);
pool->pop = NULL;
pool->base = NULL;
pool->capacity = 0;
pool->uuid_lo = 0;
}
}
free(g_pmpool_arr);
g_pmpool_arr = NULL;
g_pmpool_count = 0;
}
pthread_rwlock_unlock(&g_pmp_rwlock);
pthread_rwlock_destroy(&g_pmp_rwlock);
}