fsblobstore

Check-in Differences
Login

Check-in Differences

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Difference From fsblobstore-0.0.2 To fsblobstore-0.0.3

2024-01-30
16:14
Update changelog. check-in: 963d3786c6 user: jan tags: trunk
00:03
Update changelog. check-in: f0afcba861 user: jan tags: fsblobstore-0.0.3, trunk
00:02
Update to tmpfile 0.0.2. Add a factory method to use the 'small file' support of tmpfile. check-in: ef3e8cd6e8 user: jan tags: trunk
2024-01-28
23:32
Release maintenance. check-in: cfdf2cf9dd user: jan tags: fsblobstore-0.0.2, trunk
23:30
Re-export TmpFile. check-in: 20a3f8cf75 user: jan tags: trunk

Changes to Cargo.toml.

1
2
3

4
5
6
7
8
9
10
1
2

3
4
5
6
7
8
9
10


-
+







[package]
name = "fsblobstore"
version = "0.0.2"
version = "0.0.3"
edition = "2021"
license = "0BSD"
categories = [ "filesystem" ]
keywords = [ "blob", "datastore" ]
repository = "https://repos.qrnch.tech/pub/fsblobstore"
description = "A file-system backed blob storage abstraction."
rust-version = "1.56"
22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
37
38
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
38







-
+









get-fname = []

[dependencies]
hex = { version = "0.4.3" }
idbag = { version = "0.1.2" }
recstrm = { version = "0.0.1", optional = true }
sha2 =  { version = "0.10.8" }
tmpfile = { version = "0.0.1" }
tmpfile = { version = "0.0.2" }
walkdir = { version = "2.4.0", optional = true }

[dev-dependencies]
rand = { version = "0.8.5" }

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"]

Changes to src/lib.rs.

30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44







-
+







use idbag::IdBag;

use tmpfile::TmpProc;

use sha2::{Digest, Sha256};

pub use ch::ContentHash;
pub use tmpfile::TmpFile;
pub use tmpfile::{self, TmpFile};

pub use err::Error;


/// Internal type used by the [`TmpFile`] to hash and move blobs into their
/// final location.
struct Hasher {
52
53
54
55
56
57
58
59
60


61
62
63

64
65
66



67
68
69
70
71
72
73
74
75












76
77
78
79
80
81
82


83
84
85
86
87
88
89
52
53
54
55
56
57
58


59
60
61
62
63
64



65
66
67
68








69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96







-
-
+
+



+
-
-
-
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+







+
+







  /// Called when a buffer is about to be written.
  fn update(&mut self, buf: &[u8]) {
    self.inner.update(buf);
  }

  fn finalize(
    &mut self,
    tmpfile: &Path
  ) -> Result<(Self::Output, PathBuf), std::io::Error> {
    tmpfile: Option<&Path>
  ) -> Result<(Self::Output, Option<PathBuf>), std::io::Error> {
    let result = self.inner.clone().finalize();
    let hash = result.to_vec();

    let fname = if let Some(tmpfile) = tmpfile {
    let Some(basedir) = tmpfile.parent() else {
      panic!("foo");
    };
      let Some(basedir) = tmpfile.parent() else {
        panic!("foo");
      };

    let hexhash = hex::encode(&hash);
    let (subdir1, rest) = hexhash.split_at(2);
    let (subdir2, fname) = rest.split_at(2);
    let subdirs = basedir.join(subdir1).join(subdir2);
    if !subdirs.exists() {
      std::fs::create_dir_all(&subdirs)?;
    }
    Ok((ContentHash::from(hash), subdirs.join(fname)))
      let hexhash = hex::encode(&hash);
      let (subdir1, rest) = hexhash.split_at(2);
      let (subdir2, fname) = rest.split_at(2);
      let subdirs = basedir.join(subdir1).join(subdir2);
      if !subdirs.exists() {
        std::fs::create_dir_all(&subdirs)?;
      }
      Some(subdirs.join(fname))
    } else {
      None
    };
    Ok((ContentHash::from(hash), fname))
  }
}


/// An abstraction over a blob storage in a file system directory.
pub struct FsBlobStore {
  basedir: PathBuf,

  minsize: Option<usize>,

  /// Used to allocate unique identifiers for naming temporary files.
  idbag: IdBag
}

impl FsBlobStore {
  fn fsparts(hexhash: &str) -> (&str, &str, &str) {
114
115
116
117
118
119
120













121
122
123

124
125
126
127
128
129
130
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151







+
+
+
+
+
+
+
+
+
+
+
+
+



+







  /// The `basedir` is where the blobs and temporary files will be stored.  The
  /// caller must ensure that either `basedir` is absolute, or that the path
  /// remains valid throughout the object's lifetime.
  pub fn new(basedir: impl AsRef<Path>) -> Result<Self, Error> {
    let basedir = basedir.as_ref();
    Ok(Self {
      basedir: basedir.to_path_buf(),
      minsize: None,
      idbag: IdBag::new()
    })
  }

  pub fn with_minsize(
    basedir: impl AsRef<Path>,
    minsize: usize
  ) -> Result<Self, Error> {
    let basedir = basedir.as_ref();
    Ok(Self {
      basedir: basedir.to_path_buf(),
      minsize: Some(minsize),
      idbag: IdBag::new()
    })
  }


  /// Check if content for a hash exists in store.
  pub fn have(&self, hash: &[u8]) -> Result<bool, std::io::Error> {
    let fname = self.abspathname(hash);
    fname.try_exists()
  }

144
145
146
147
148
149
150



151


152
153
154
155
156
157
158
165
166
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
182
183







+
+
+
-
+
+







    let id = self.idbag.alloc();
    let tmpfname = format!("tmp-{:08x}", id.val());
    let tp = Hasher {
      inner: Sha256::new(),
      _id: id
    };
    let tmpfname = self.basedir.join(tmpfname);
    if let Some(minsize) = self.minsize {
      TmpFile::with_minsize(tmpfname, Box::new(tp), minsize)
    } else {
    TmpFile::new(tmpfname, Box::new(tp))
      TmpFile::new(tmpfname, Box::new(tp))
    }
  }

  /// Remove a blob from the blob store.
  ///
  /// # Panic
  /// If the `hash` is not 32 bytes long this method will panic.
  pub fn rm(&self, hash: &[u8]) -> Result<(), std::io::Error> {

Changes to www/changelog.md.

1
2
3
4
5
6
7
8




9


10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22








+
+
+
+

+
+







# Change Log

## [Unreleased]

[Details](/vdiff?from=fsblobstore-0.0.2&to=trunk)

### Added

- Add factory method `FsBlobStore::with_minsize()` to be able to use the memory
  buffer for "small files" support introduced in `tmpfile` 0.0.2.
- Re-export `tmpfile` to allow application to access `tmpfile::Output`.

### Changed

- Update to `tmpfile` 0.0.2.

### Removed

---

## [0.0.2] - 2024-01-29