Skip to content
This repository has been archived by the owner on Sep 17, 2024. It is now read-only.

Index update one #91

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion arklib/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion arklib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ name = "arklib"
crate-type = ["cdylib", "staticlib"]

[dependencies]
arklib = { git = "https://github.com/ARK-builders/arklib", rev = "03add5a" }
arklib = { git = "https://github.com/ARK-builders/arklib", rev = "82ba6ac" }
anyhow = "1.0.58"
env_logger = "0.9.0"
canonical-path = "2.0.2"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mberry That's what we want to get rid of and keep the bindings thin.

url = { version = "2.2.2", features = ["serde"] }
openssl = { version = "0.10.42", features = ["vendored"] }
image = "0.24.2"
Expand Down
158 changes: 106 additions & 52 deletions arklib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ pub mod android {
use arklib::pdf::PDFQuality;

use std::path::PathBuf;
use std::str::FromStr;
use std::sync::{Arc, RwLock};
use std::{fs::File, path::Path};

use canonical_path::CanonicalPathBuf;

use anyhow::Error;
use image::EncodableLayout;
use log::{debug, trace, Level};
Expand Down Expand Up @@ -49,31 +52,8 @@ pub mod android {

let resourceId = ResourceId::compute(data_size.try_into().unwrap(), file_path).unwrap();

let resource_id_cls = env.find_class("dev/arkbuilders/arklib/ResourceId").unwrap();

let create_resource_id_fn = env
.get_static_method_id(
resource_id_cls,
"create",
"(JJ)Ldev/arkbuilders/arklib/ResourceId;",
)
.unwrap();

let data_size: jlong = resourceId.data_size as usize as i64;
let crc32: jlong = resourceId.crc32 as usize as i64;

trace!("after uszie");
let resource_id = env
.call_static_method_unchecked(
resource_id_cls,
create_resource_id_fn,
JavaType::Object(String::from("dev/arkbuilders/arklib/ResourceId")),
&[JValue::from(data_size), JValue::from(crc32)],
)
.unwrap()
.l()
.unwrap();
resource_id.into_inner()
let resource_id = id_to_jni_id(env, &resourceId);
resource_id.l().unwrap().into_inner()
}

#[no_mangle]
Expand Down Expand Up @@ -422,60 +402,121 @@ pub mod android {
}

#[no_mangle]
pub extern "C" fn Java_dev_arkbuilders_arklib_binding_BindingIndex_updateNative(
pub extern "C" fn Java_dev_arkbuilders_arklib_binding_BindingIndex_updateAllNative(
env: JNIEnv,
_: JClass,
jni_root: JString,
) -> jobject {
let result = match provide_index(env, jni_root) {
Ok(rwlock) => {
let mut index = rwlock.write().unwrap();
index.update().unwrap()
index.update_all().unwrap()
}
Err(err) => {
panic!("couldn't provide index {}", err)
}
};

let jni_deleted_list = env.new_object("java/util/ArrayList", "()V", &[]).unwrap();
let jni_deleted_set = env.new_object("java/util/HashSet", "()V", &[]).unwrap();
let jni_added_map = env.new_object("java/util/HashMap", "()V", &[]).unwrap();

for id in &result.deleted {
let id = env.new_string(id.to_string()).unwrap().into();
let jni_id = id_to_jni_id(env, id);

env.call_method(jni_deleted_list, "add", "(Ljava/lang/Object;)Z", &[id])
env.call_method(jni_deleted_set, "add", "(Ljava/lang/Object;)Z", &[jni_id])
.unwrap();
}

for (path, id) in &result.added {
let id = env.new_string(id.to_string()).unwrap().into();
let path = env.new_string(path.to_str().unwrap()).unwrap().into();
let jni_id = id_to_jni_id(env, id);
let jni_path = env.new_string(path.to_str().unwrap()).unwrap().into();

env.call_method(
jni_added_map,
"put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
&[id, path],
&[jni_id, jni_path],
)
.unwrap();
}

let jni_params_list = env.new_object("java/util/ArrayList", "()V", &[]).unwrap();
env.call_method(
jni_params_list,
"add",
"(Ljava/lang/Object;)Z",
&[jni_deleted_list.into()],
)
.unwrap();
env.call_method(
jni_params_list,
"add",
"(Ljava/lang/Object;)Z",
&[jni_added_map.into()],
)
.unwrap();
let jni_raw_updates = env
.new_object(
"dev/arkbuilders/arklib/binding/RawUpdates",
"(Ljava/util/HashSet;Ljava/util/HashMap;)V",
&[jni_deleted_set.into(), jni_added_map.into()],
)
.unwrap();

jni_params_list.into_inner()
jni_raw_updates.into_inner()
}

#[no_mangle]
pub extern "C" fn Java_dev_arkbuilders_arklib_binding_BindingIndex_updateOneNative(
env: JNIEnv,
_: JClass,
jni_root: JString,
jni_path: JString,
jni_old_id: JString,
) -> jobject {
let path: String = env
.get_string(jni_path)
.expect("Failed to parse path")
.into();

let path: &Path = Path::new(&path);

let old_id_str: String = env
.get_string(jni_old_id)
.expect("Failed to parse old id")
.into();

let old_id = ResourceId::from_str(&old_id_str).unwrap();

let result = match provide_index(env, jni_root) {
Ok(rwlock) => {
let mut index = rwlock.write().unwrap();
index
.update_one(CanonicalPathBuf::canonicalize(path).unwrap(), old_id)
.unwrap()
}
Err(err) => {
panic!("couldn't provide index {}", err)
}
};

let jni_deleted_set = env.new_object("java/util/HashSet", "()V", &[]).unwrap();
let jni_added_map = env.new_object("java/util/HashMap", "()V", &[]).unwrap();

for id in &result.deleted {
let jni_id = id_to_jni_id(env, id);

env.call_method(jni_deleted_set, "add", "(Ljava/lang/Object;)Z", &[jni_id])
.unwrap();
}

for (path, id) in &result.added {
let jni_id = id_to_jni_id(env, id);
let jni_path = env.new_string(path.to_str().unwrap()).unwrap().into();

env.call_method(
jni_added_map,
"put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
&[jni_id, jni_path],
)
.unwrap();
}

let jni_raw_updates = env
.new_object(
"dev/arkbuilders/arklib/binding/RawUpdates",
"(Ljava/util/HashSet;Ljava/util/HashMap;)V",
&[jni_deleted_set.into(), jni_added_map.into()],
)
.unwrap();

jni_raw_updates.into_inner()
}

#[no_mangle]
Expand All @@ -501,20 +542,33 @@ pub mod android {
let jni_map = env.new_object("java/util/HashMap", "()V", &[]).unwrap();

for (id, path) in &index.id2path {
let id = env.new_string(id.to_string()).unwrap().into();
let path = env.new_string(path.to_str().unwrap()).unwrap().into();
let jni_id = id_to_jni_id(env, id);
let jni_path = env.new_string(path.to_str().unwrap()).unwrap().into();
env.call_method(
jni_map,
"put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
&[id, path],
&[jni_id, jni_path],
)
.unwrap();
}

jni_map.into_inner()
}

fn id_to_jni_id<'a>(env: JNIEnv<'a>, id: &'a ResourceId) -> JValue<'a> {
let data_size: jlong = id.data_size as usize as i64;
let crc32: jlong = id.crc32 as usize as i64;

env.new_object(
"dev/arkbuilders/arklib/ResourceId",
"(JJ)V",
&[JValue::from(data_size), JValue::from(crc32)],
)
.unwrap()
.into()
}

fn provide_index(env: JNIEnv, jni_root: JString) -> Result<Arc<RwLock<ResourceIndex>>, Error> {
let root_string: String = env.get_string(jni_root).unwrap().into();
trace!("providing index for root {}", &root_string);
Expand Down
2 changes: 1 addition & 1 deletion lib/src/main/java/space/taran/arklib/Lib.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ data class ResourceId(

fun fromString(str: String): ResourceId {
val parts = str.split(KEY_VALUE_SEPARATOR)
return ResourceId(
return ResourceId(
parts[0].toLong(),
parts[1].toLong()
)
Expand Down
32 changes: 16 additions & 16 deletions lib/src/main/java/space/taran/arklib/binding/BindingIndex.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,32 @@ import java.nio.file.Path
import kotlin.io.path.Path

class RawUpdates(
val deleted: Set<ResourceId>,
val added: Map<ResourceId, Path>
val deleted: HashSet<ResourceId>,
val added: HashMap<ResourceId, String>,
)

object BindingIndex {
private external fun loadNative(root: String): Boolean
fun load(root: Path): Boolean = loadNative(root.toString())

private external fun updateNative(root: String): List<Any>
fun update(root: Path): RawUpdates {
val list = updateNative(root.toString())
val deleted = (list[0] as List<String>).map {
ResourceId.fromString(it)
}.toSet()
val added = (list[1] as HashMap<String, String>).map { (id, path) ->
ResourceId.fromString(id) to Path(path)
}.toMap()
return RawUpdates(deleted, added)
}
private external fun updateAllNative(root: String): RawUpdates
fun updateAll(root: Path) = updateAllNative(root.toString())

private external fun updateOneNative(
root: String,
path: String,
oldId: String
): RawUpdates

fun updateOne(root: Path, path: Path, oldId: ResourceId) =
updateOneNative(root.toString(), path.toString(), oldId.toString())

private external fun storeNative(root: String)
fun store(root: Path) = storeNative(root.toString())

private external fun id2pathNative(root: String): HashMap<String, String>
private external fun id2pathNative(root: String): HashMap<ResourceId, String>
fun id2path(root: Path): Map<ResourceId, Path> =
id2pathNative(root.toString()).map { (idStr, pathStr) ->
ResourceId.fromString(idStr) to Path(pathStr)
id2pathNative(root.toString()).map { (id, pathStr) ->
id to Path(pathStr)
}.toMap()
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,16 @@ class IndexAggregation(
override suspend fun updateAll() {
shards.forEach { it.updateAll() }
}

override suspend fun updateOne(
resourcePath: Path,
oldId: ResourceId
): ResourceUpdates {
return shards.find { resourcePath.startsWith(it.path) }
?.updateOne(resourcePath, oldId)
?: error(
"At least one shard must contain the passed path" +
"shards: ${shards.map { it.path }} path: $resourcePath"
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ class IndexProjection(

override suspend fun updateAll() = root.updateAll()

override suspend fun updateOne(resourcePath: Path, oldId: ResourceId) =
root.updateOne(resourcePath, oldId)

override fun allResources(): Map<ResourceId, Resource> {
val allPathsMap = root.allPaths()
return root
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ interface ResourceIndex {

suspend fun updateAll()

suspend fun updateOne(resourcePath: Path, oldId: ResourceId): ResourceUpdates

suspend fun updateOne(oldId: ResourceId): ResourceUpdates = updateOne(
allPaths()[oldId]!!,
oldId
)

fun allResources(): Map<ResourceId, Resource>

fun getResource(id: ResourceId): Resource?
Expand Down
Loading