You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2024/08/27 15:59:33 UTC

(opendal) branch main updated: fix(services/memory): blocking_scan right range (#5062)

This is an automated email from the ASF dual-hosted git repository.

xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new 41fe460e8b fix(services/memory): blocking_scan right range (#5062)
41fe460e8b is described below

commit 41fe460e8b9cae24f749b840f3da8361342257d5
Author: meteorgan <me...@gmail.com>
AuthorDate: Tue Aug 27 23:59:28 2024 +0800

    fix(services/memory): blocking_scan right range (#5062)
    
    * fix(serivces/memory) blocking scan right range
    
    * cargo fmt
    
    * cargo clippy
---
 core/src/raw/path.rs                |  2 +-
 core/src/services/memory/backend.rs | 48 +++++++++++++++++++++++++++----------
 2 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/core/src/raw/path.rs b/core/src/raw/path.rs
index db4d047616..fb3c4ad07a 100644
--- a/core/src/raw/path.rs
+++ b/core/src/raw/path.rs
@@ -130,7 +130,7 @@ pub fn normalize_path(path: &str) -> String {
 /// - Add leading `/` if not starts with: `abc/` => `/abc/`
 /// - Add trailing `/` if not ends with: `/abc` => `/abc/`
 ///
-/// Finally, we will got path like `/path/to/root/`.
+/// Finally, we will get path like `/path/to/root/`.
 pub fn normalize_root(v: &str) -> String {
     let mut v = v
         .split('/')
diff --git a/core/src/services/memory/backend.rs b/core/src/services/memory/backend.rs
index a231bffdf2..558c5650dc 100644
--- a/core/src/services/memory/backend.rs
+++ b/core/src/services/memory/backend.rs
@@ -125,19 +125,18 @@ impl typed_kv::Adapter for Adapter {
 
     fn blocking_scan(&self, path: &str) -> Result<Vec<String>> {
         let inner = self.inner.lock().unwrap();
-        let keys: Vec<_> = if path.is_empty() {
-            inner.keys().cloned().collect()
-        } else {
-            let right_range = if let Some(path) = path.strip_suffix('/') {
-                format!("{}0", path)
-            } else {
-                format!("{}{}", path, std::char::MAX)
-            };
-            inner
-                .range(path.to_string()..right_range)
-                .map(|(k, _)| k.to_string())
-                .collect()
-        };
+
+        if path.is_empty() {
+            return Ok(inner.keys().cloned().collect());
+        }
+
+        let mut keys = Vec::new();
+        for (key, _) in inner.range(path.to_string()..) {
+            if !key.starts_with(path) {
+                break;
+            }
+            keys.push(key.to_string());
+        }
         Ok(keys)
     }
 }
@@ -145,6 +144,8 @@ impl typed_kv::Adapter for Adapter {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use crate::raw::adapters::typed_kv::{Adapter, Value};
+    use crate::services::memory::backend;
 
     #[test]
     fn test_accessor_metadata_name() {
@@ -154,4 +155,25 @@ mod tests {
         let b2 = MemoryBuilder::default().build().unwrap();
         assert_ne!(b1.info().name(), b2.info().name())
     }
+
+    #[test]
+    fn test_blocking_scan() {
+        let adapter = backend::Adapter {
+            inner: Arc::new(Mutex::new(BTreeMap::default())),
+        };
+
+        adapter.blocking_set("aaa/bbb/", Value::new_dir()).unwrap();
+        adapter.blocking_set("aab/bbb/", Value::new_dir()).unwrap();
+        adapter.blocking_set("aab/ccc/", Value::new_dir()).unwrap();
+        adapter
+            .blocking_set(&format!("aab{}aaa/", std::char::MAX), Value::new_dir())
+            .unwrap();
+        adapter.blocking_set("aac/bbb/", Value::new_dir()).unwrap();
+
+        let data = adapter.blocking_scan("aab").unwrap();
+        assert_eq!(data.len(), 3);
+        for path in data {
+            assert!(path.starts_with("aab"));
+        }
+    }
 }