mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-08-16 00:43:11 +00:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a1cec2cd60 | |||
| b66f247580 | |||
| 16f2a32bb7 | |||
| 472444ed8e | |||
| bb03805b58 | |||
| e4f955d672 | |||
| ea9b15f669 | |||
| 2e6bb3f766 | |||
| 375270afd1 | |||
| c783194e8b | |||
| fdcd7dee5a | |||
| 0f0795103d | |||
| c9d26e8c50 | |||
| b925f53dc3 | |||
| 2f495575d8 | |||
| 9e0a9c1c15 | |||
| 9c788059e2 | |||
| 5684e1990c | |||
| 14c50f2f84 | |||
| 0fab9c3b8c | |||
| 75759a163c | |||
| d2deee0b8b | |||
| 8499cd5c21 | |||
| 4ea7983093 | |||
| d5e39d11eb | |||
| 6d3ace1ea9 | |||
| 833cf082da | |||
| 1ecd88c01f | |||
| 5efcdc0de3 | |||
| a16eb7e4b8 | |||
| 6742070517 | |||
| 6894878146 | |||
| 02b0ba5f44 | |||
| fb3bd11dce | |||
| c168383113 | |||
| 04a0063df9 |
Generated
+332
-198
File diff suppressed because it is too large
Load Diff
+12
@@ -11,10 +11,22 @@ members = [
|
||||
"src/web",
|
||||
"src/garage",
|
||||
"src/k2v-client",
|
||||
"src/format-table",
|
||||
]
|
||||
|
||||
default-members = ["src/garage"]
|
||||
|
||||
[workspace.dependencies]
|
||||
format_table = { version = "0.1.0", path = "src/format-table" }
|
||||
garage_api = { version = "0.8.2", path = "src/api" }
|
||||
garage_block = { version = "0.8.2", path = "src/block" }
|
||||
garage_db = { version = "0.8.2", path = "src/db", default-features = false }
|
||||
garage_model = { version = "0.8.2", path = "src/model", default-features = false }
|
||||
garage_rpc = { version = "0.8.2", path = "src/rpc" }
|
||||
garage_table = { version = "0.8.2", path = "src/table" }
|
||||
garage_util = { version = "0.8.2", path = "src/util" }
|
||||
garage_web = { version = "0.8.2", path = "src/web" }
|
||||
|
||||
[profile.dev]
|
||||
lto = "off"
|
||||
|
||||
|
||||
@@ -349,5 +349,5 @@ and is covered in the [quick start guide](@/documentation/quick-start/_index.md)
|
||||
Remember also that the CLI is self-documented thanks to the `--help` flag and
|
||||
the `help` subcommand (e.g. `garage help`, `garage key --help`).
|
||||
|
||||
Configuring S3-compatible applicatiosn to interact with Garage
|
||||
Configuring S3-compatible applications to interact with Garage
|
||||
is covered in the [Integrations](@/documentation/connect/_index.md) section.
|
||||
|
||||
Generated
+76
-23
@@ -41,12 +41,15 @@
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1659877975,
|
||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||
"lastModified": 1681202837,
|
||||
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -56,12 +59,15 @@
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1667395993,
|
||||
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
|
||||
"lastModified": 1681202837,
|
||||
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
|
||||
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -72,44 +78,61 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1665657542,
|
||||
"narHash": "sha256-mojxNyzbvmp8NtVtxqiHGhRfjCALLfk9i/Uup68Y5q8=",
|
||||
"lastModified": 1682109806,
|
||||
"narHash": "sha256-d9g7RKNShMLboTWwukM+RObDWWpHKaqTYXB48clBWXI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a3073c49bc0163fea6a121c276f526837672b555",
|
||||
"rev": "2362848adf8def2866fabbffc50462e929d7fffb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1682423271,
|
||||
"narHash": "sha256-WHhl1GiOij1ob4cTLL+yhqr+vFOUH8E5wAX8Ir8fvjE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "94517a501434a627c5d9e72ac6e7f26174b978d3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a3073c49bc0163fea6a121c276f526837672b555",
|
||||
"rev": "94517a501434a627c5d9e72ac6e7f26174b978d3",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"cargo2nix": "cargo2nix",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"cargo2nix",
|
||||
"flake-compat"
|
||||
],
|
||||
"flake-utils": [
|
||||
"cargo2nix",
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"cargo2nix",
|
||||
"nixpkgs"
|
||||
]
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1664247556,
|
||||
"narHash": "sha256-J4vazHU3609ekn7dr+3wfqPo5WGlZVAgV7jfux352L0=",
|
||||
"lastModified": 1682389182,
|
||||
"narHash": "sha256-8t2nmFnH+8V48+IJsf8AK51ebXNlVbOSVYOpiqJKvJE=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "524db9c9ea7bc7743bb74cdd45b6d46ea3fcc2ab",
|
||||
"rev": "74f1a64dd28faeeb85ef081f32cad2989850322c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -117,6 +140,36 @@
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
|
||||
@@ -2,16 +2,30 @@
|
||||
description =
|
||||
"Garage, an S3-compatible distributed object store for self-hosted deployments";
|
||||
|
||||
# Nixpkgs unstable as of 2023-04-25, has rustc v1.68
|
||||
inputs.nixpkgs.url =
|
||||
"github:NixOS/nixpkgs/a3073c49bc0163fea6a121c276f526837672b555";
|
||||
"github:NixOS/nixpkgs/94517a501434a627c5d9e72ac6e7f26174b978d3";
|
||||
|
||||
inputs.cargo2nix = {
|
||||
# As of 2022-10-18: two small patches over unstable branch, one for clippy and one to fix feature detection
|
||||
url = "github:Alexis211/cargo2nix/a7a61179b66054904ef6a195d8da736eaaa06c36";
|
||||
|
||||
# As of 2023-04-25:
|
||||
# - my two patches were merged into unstable (one for clippy and one to "fix" feature detection)
|
||||
# - rustc v1.66
|
||||
# url = "github:cargo2nix/cargo2nix/8fb57a670f7993bfc24099c33eb9c5abb51f29a2";
|
||||
|
||||
# Rust overlay as of 2023-04-25
|
||||
inputs.rust-overlay.url =
|
||||
"github:oxalica/rust-overlay/74f1a64dd28faeeb85ef081f32cad2989850322c";
|
||||
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
||||
|
||||
outputs = { self, nixpkgs, cargo2nix, flake-utils }:
|
||||
inputs.flake-utils.follows = "cargo2nix/flake-utils";
|
||||
inputs.flake-compat.follows = "cargo2nix/flake-compat";
|
||||
|
||||
outputs = { self, nixpkgs, cargo2nix, flake-utils, ... }:
|
||||
let
|
||||
git_version = self.lastModifiedDate;
|
||||
compile = import ./nix/compile.nix;
|
||||
|
||||
+10
-15
@@ -1,19 +1,14 @@
|
||||
rec {
|
||||
# * Fixed dependencies
|
||||
pkgsSrc = fetchTarball {
|
||||
# As of 2022-10-13
|
||||
let
|
||||
lock = builtins.fromJSON (builtins.readFile ../flake.lock);
|
||||
flakeCompatRev = lock.nodes.flake-compat.locked.rev;
|
||||
flakeCompat = fetchTarball {
|
||||
url =
|
||||
"https://github.com/NixOS/nixpkgs/archive/a3073c49bc0163fea6a121c276f526837672b555.zip";
|
||||
sha256 = "1bz632psfbpmicyzjb8b4265y50shylccvfm6ry6mgnv5hvz324s";
|
||||
"https://github.com/edolstra/flake-compat/archive/${flakeCompatRev}.tar.gz";
|
||||
sha256 = lock.nodes.flake-compat.locked.narHash;
|
||||
};
|
||||
cargo2nixSrc = fetchGit {
|
||||
# As of 2022-10-18: two small patches over unstable branch, one for clippy and one to fix feature detection
|
||||
url = "https://github.com/Alexis211/cargo2nix";
|
||||
ref = "custom_unstable";
|
||||
rev = "a7a61179b66054904ef6a195d8da736eaaa06c36";
|
||||
};
|
||||
|
||||
# * Shared objects
|
||||
cargo2nix = import cargo2nixSrc;
|
||||
flake = ((import flakeCompat) { src = ../.; }).defaultNix;
|
||||
in rec {
|
||||
pkgsSrc = flake.inputs.nixpkgs;
|
||||
cargo2nix = flake.inputs.cargo2nix;
|
||||
cargo2nixOverlay = cargo2nix.overlays.default;
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ let
|
||||
*/
|
||||
toolchainOptions = if target == null || target == "x86_64-unknown-linux-musl"
|
||||
|| target == "aarch64-unknown-linux-musl" then {
|
||||
rustVersion = "1.63.0";
|
||||
rustVersion = "1.68.0";
|
||||
extraRustComponents = [ "clippy" ];
|
||||
} else {
|
||||
rustToolchain = pkgs.symlinkJoin {
|
||||
|
||||
+2
-2
@@ -1,13 +1,13 @@
|
||||
pkgs:
|
||||
pkgs.buildGoModule rec {
|
||||
pname = "kaniko";
|
||||
version = "1.6.0";
|
||||
version = "1.9.2";
|
||||
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "GoogleContainerTools";
|
||||
repo = "kaniko";
|
||||
rev = "v${version}";
|
||||
sha256 = "1fnclr556avxay6pvgw5ya3xbxfnf2gv4njq2hr4fd6fcjyslq5h";
|
||||
sha256 = "dXQ0/o1qISv+sjNVIpfF85bkbM9sGOGwqVbWZpMWfMY=";
|
||||
};
|
||||
|
||||
vendorSha256 = null;
|
||||
|
||||
@@ -15,7 +15,7 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.4.0
|
||||
version: 0.4.1
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
|
||||
@@ -4,9 +4,28 @@
|
||||
|
||||
# Garage configuration. These values go to garage.toml
|
||||
garage:
|
||||
# Can be changed for better performance on certain systems
|
||||
# https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#db-engine-since-v0-8-0
|
||||
dbEngine: "sled"
|
||||
|
||||
# Defaults is 1MB
|
||||
# An increase can result in better performance in certain scenarios
|
||||
# https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#block-size
|
||||
blockSize: "1048576"
|
||||
|
||||
# Tuning parameters for the sled DB engine
|
||||
# https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#sled-cache-capacity
|
||||
sledCacheCapacity: "134217728"
|
||||
sledFlushEveryMs: "2000"
|
||||
|
||||
# Default to 3 replicas, see the replication_mode section at
|
||||
# https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/
|
||||
# https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#replication-mode
|
||||
replicationMode: "3"
|
||||
|
||||
# zstd compression level of stored blocks
|
||||
# https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#compression-level
|
||||
compressionLevel: "1"
|
||||
|
||||
rpcBindAddr: "[::]:3901"
|
||||
# If not given, a random secret will be generated and stored in a Secret object
|
||||
rpcSecret: ""
|
||||
@@ -27,8 +46,19 @@ garage:
|
||||
metadata_dir = "/mnt/meta"
|
||||
data_dir = "/mnt/data"
|
||||
|
||||
db_engine = "{{ .Values.garage.dbEngine }}"
|
||||
|
||||
block_size = {{ .Values.garage.blockSize }}
|
||||
|
||||
{{- if eq .Values.garage.dbEngine "sled"}}
|
||||
sled_cache_capacity = {{ .Values.garage.sledCacheCapacity }}
|
||||
sled_flush_every_ms = {{ .Values.garage.sledFlushEveryMs }}
|
||||
{{- end }}
|
||||
|
||||
replication_mode = "{{ .Values.garage.replicationMode }}"
|
||||
|
||||
compression_level = {{ .Values.garage.compressionLevel }}
|
||||
|
||||
rpc_bind_addr = "{{ .Values.garage.rpcBindAddr }}"
|
||||
# rpc_secret will be populated by the init container from a k8s secret object
|
||||
rpc_secret = "__RPC_SECRET_REPLACE__"
|
||||
@@ -49,7 +79,7 @@ garage:
|
||||
bind_addr = "[::]:3902"
|
||||
root_domain = "{{ .Values.garage.s3.web.rootDomain }}"
|
||||
index = "{{ .Values.garage.s3.web.index }}"
|
||||
|
||||
|
||||
[admin]
|
||||
api_bind_addr = "[::]:3903"
|
||||
{{- if .Values.monitoring.tracing.sink }}
|
||||
@@ -211,4 +241,4 @@ monitoring:
|
||||
scrapeTimeout: 10s
|
||||
relabelings: []
|
||||
tracing:
|
||||
sink: ""
|
||||
sink: ""
|
||||
|
||||
+6
-6
@@ -14,11 +14,11 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_model = { version = "0.8.2", path = "../model" }
|
||||
garage_table = { version = "0.8.2", path = "../table" }
|
||||
garage_block = { version = "0.8.2", path = "../block" }
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_rpc = { version = "0.8.2", path = "../rpc" }
|
||||
garage_model.workspace = true
|
||||
garage_table.workspace = true
|
||||
garage_block.workspace = true
|
||||
garage_util.workspace = true
|
||||
garage_rpc.workspace = true
|
||||
|
||||
async-trait = "0.1.7"
|
||||
base64 = "0.21"
|
||||
@@ -51,7 +51,7 @@ roxmltree = "0.14"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_bytes = "0.11"
|
||||
serde_json = "1.0"
|
||||
quick-xml = { version = "0.21", features = [ "serialize" ] }
|
||||
quick-xml = { version = "0.26", features = [ "serialize" ] }
|
||||
url = "2.3"
|
||||
|
||||
opentelemetry = "0.17"
|
||||
|
||||
@@ -105,7 +105,7 @@ impl AdminApiServer {
|
||||
let bucket_id = self
|
||||
.garage
|
||||
.bucket_helper()
|
||||
.resolve_global_bucket_name(&domain)
|
||||
.resolve_global_bucket_name(domain)
|
||||
.await?
|
||||
.ok_or(HelperError::NoSuchBucket(domain.to_string()))?;
|
||||
|
||||
|
||||
@@ -183,8 +183,8 @@ async fn bucket_info_results(
|
||||
}
|
||||
}),
|
||||
keys: relevant_keys
|
||||
.into_iter()
|
||||
.map(|(_, key)| {
|
||||
.into_values()
|
||||
.map(|key| {
|
||||
let p = key.state.as_option().unwrap();
|
||||
GetBucketInfoKey {
|
||||
access_key_id: key.key_id,
|
||||
|
||||
@@ -183,8 +183,8 @@ async fn key_info_results(garage: &Arc<Garage>, key: Key) -> Result<Response<Bod
|
||||
create_bucket: *key_state.allow_create_bucket.get(),
|
||||
},
|
||||
buckets: relevant_buckets
|
||||
.into_iter()
|
||||
.map(|(_, bucket)| {
|
||||
.into_values()
|
||||
.map(|bucket| {
|
||||
let state = bucket.state.as_option().unwrap();
|
||||
KeyInfoBucketResult {
|
||||
id: hex::encode(bucket.id),
|
||||
|
||||
@@ -128,7 +128,7 @@ impl<A: ApiHandler> ApiServer<A> {
|
||||
let uri = req.uri().clone();
|
||||
|
||||
if let Ok(forwarded_for_ip_addr) =
|
||||
forwarded_headers::handle_forwarded_for_headers(&req.headers())
|
||||
forwarded_headers::handle_forwarded_for_headers(req.headers())
|
||||
{
|
||||
info!(
|
||||
"{} (via {}) {} {}",
|
||||
|
||||
@@ -282,8 +282,8 @@ pub(crate) async fn handle_poll_range(
|
||||
if let Some((items, seen_marker)) = resp {
|
||||
let resp = PollRangeResponse {
|
||||
items: items
|
||||
.into_iter()
|
||||
.map(|(_k, i)| ReadBatchResponseItem::from(i))
|
||||
.into_values()
|
||||
.map(ReadBatchResponseItem::from)
|
||||
.collect::<Vec<_>>(),
|
||||
seen_marker,
|
||||
};
|
||||
|
||||
+2
-2
@@ -443,7 +443,7 @@ fn body_from_blocks_range(
|
||||
// block.part_number, which is not the same in the case of a multipart upload)
|
||||
let mut blocks: Vec<(VersionBlock, u64)> = Vec::with_capacity(std::cmp::min(
|
||||
all_blocks.len(),
|
||||
4 + ((end - begin) / std::cmp::max(all_blocks[0].1.size as u64, 1024)) as usize,
|
||||
4 + ((end - begin) / std::cmp::max(all_blocks[0].1.size, 1024)) as usize,
|
||||
));
|
||||
let mut block_offset: u64 = 0;
|
||||
for (_, b) in all_blocks.iter() {
|
||||
@@ -454,7 +454,7 @@ fn body_from_blocks_range(
|
||||
if block_offset < end && block_offset + b.size > begin {
|
||||
blocks.push((*b, block_offset));
|
||||
}
|
||||
block_offset += b.size as u64;
|
||||
block_offset += b.size;
|
||||
}
|
||||
|
||||
let order_stream = OrderTag::stream();
|
||||
|
||||
@@ -14,10 +14,10 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_db = { version = "0.8.2", path = "../db" }
|
||||
garage_rpc = { version = "0.8.2", path = "../rpc" }
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_table = { version = "0.8.2", path = "../table" }
|
||||
garage_db.workspace = true
|
||||
garage_rpc.workspace = true
|
||||
garage_util.workspace = true
|
||||
garage_table.workspace = true
|
||||
|
||||
opentelemetry = "0.17"
|
||||
|
||||
@@ -37,7 +37,7 @@ serde_bytes = "0.11"
|
||||
futures = "0.3"
|
||||
futures-util = "0.3"
|
||||
tokio = { version = "1.0", default-features = false, features = ["rt", "rt-multi-thread", "io-util", "net", "time", "macros", "sync", "signal", "fs"] }
|
||||
tokio-util = { version = "0.6", features = ["io"] }
|
||||
tokio-util = { version = "0.7", features = ["io"] }
|
||||
|
||||
[features]
|
||||
system-libs = [ "zstd/pkg-config" ]
|
||||
|
||||
+25
-5
@@ -600,12 +600,32 @@ impl BlockManager {
|
||||
/// Utility: check if block is stored compressed. Error if block is not stored
|
||||
async fn is_block_compressed(&self, hash: &Hash) -> Result<bool, Error> {
|
||||
let mut path = self.block_path(hash);
|
||||
path.set_extension("zst");
|
||||
if fs::metadata(&path).await.is_ok() {
|
||||
return Ok(true);
|
||||
|
||||
// If compression is disabled on node - check for the raw block
|
||||
// first and then a compressed one (as compression may have been
|
||||
// previously enabled).
|
||||
match self.compression_level {
|
||||
None => {
|
||||
if fs::metadata(&path).await.is_ok() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
path.set_extension("zst");
|
||||
|
||||
fs::metadata(&path).await.map(|_| true).map_err(Into::into)
|
||||
}
|
||||
_ => {
|
||||
path.set_extension("zst");
|
||||
|
||||
if fs::metadata(&path).await.is_ok() {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
path.set_extension("");
|
||||
|
||||
fs::metadata(&path).await.map(|_| false).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
path.set_extension("");
|
||||
fs::metadata(&path).await.map(|_| false).map_err(Into::into)
|
||||
}
|
||||
|
||||
async fn lock_mutate(&self, hash: &Hash) -> MutexGuard<'_, BlockManagerLocked> {
|
||||
|
||||
+16
-12
@@ -220,14 +220,12 @@ fn randomize_next_scrub_run_time(timestamp: u64) -> u64 {
|
||||
// Take SCRUB_INTERVAL and mix in a random interval of 10 days to attempt to
|
||||
// balance scrub load across different cluster nodes.
|
||||
|
||||
let next_run_timestamp = timestamp
|
||||
timestamp
|
||||
+ SCRUB_INTERVAL
|
||||
.saturating_add(Duration::from_secs(
|
||||
rand::thread_rng().gen_range(0..3600 * 24 * 10),
|
||||
))
|
||||
.as_millis() as u64;
|
||||
|
||||
next_run_timestamp
|
||||
.as_millis() as u64
|
||||
}
|
||||
|
||||
impl Default for ScrubWorkerPersisted {
|
||||
@@ -241,18 +239,14 @@ impl Default for ScrubWorkerPersisted {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
enum ScrubWorkerState {
|
||||
Running(BlockStoreIterator),
|
||||
Paused(BlockStoreIterator, u64), // u64 = time when to resume scrub
|
||||
#[default]
|
||||
Finished,
|
||||
}
|
||||
|
||||
impl Default for ScrubWorkerState {
|
||||
fn default() -> Self {
|
||||
ScrubWorkerState::Finished
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ScrubWorkerCommand {
|
||||
Start,
|
||||
@@ -281,6 +275,7 @@ impl ScrubWorker {
|
||||
ScrubWorkerCommand::Start => {
|
||||
self.work = match std::mem::take(&mut self.work) {
|
||||
ScrubWorkerState::Finished => {
|
||||
info!("Scrub worker initializing, now performing datastore scrub");
|
||||
let iterator = BlockStoreIterator::new(&self.manager);
|
||||
ScrubWorkerState::Running(iterator)
|
||||
}
|
||||
@@ -394,12 +389,21 @@ impl Worker for ScrubWorker {
|
||||
.tranquilizer
|
||||
.tranquilize_worker(self.persister.get_with(|p| p.tranquility)))
|
||||
} else {
|
||||
let now = now_msec();
|
||||
let next_scrub_timestamp = randomize_next_scrub_run_time(now);
|
||||
|
||||
self.persister.set_with(|p| {
|
||||
p.time_last_complete_scrub = now_msec();
|
||||
p.time_next_run_scrub = randomize_next_scrub_run_time(now_msec());
|
||||
p.time_last_complete_scrub = now;
|
||||
p.time_next_run_scrub = next_scrub_timestamp;
|
||||
})?;
|
||||
self.work = ScrubWorkerState::Finished;
|
||||
self.tranquilizer.clear();
|
||||
|
||||
info!(
|
||||
"Datastore scrub completed, next scrub scheduled for {}",
|
||||
msec_to_rfc3339(next_scrub_timestamp)
|
||||
);
|
||||
|
||||
Ok(WorkerState::Idle)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,6 +349,6 @@ pub fn recommended_map_size() -> usize {
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub fn recommended_map_size() -> usize {
|
||||
warn!("LMDB is not recommended on 32-bit systems, database size will be limited");
|
||||
tracing::warn!("LMDB is not recommended on 32-bit systems, database size will be limited");
|
||||
1usize << 30
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "format_table"
|
||||
version = "0.1.0"
|
||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||
edition = "2018"
|
||||
license = "AGPL-3.0"
|
||||
description = "Format tables with a stupid API"
|
||||
repository = "https://git.deuxfleurs.fr/Deuxfleurs/garage"
|
||||
readme = "README.md"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
@@ -0,0 +1,13 @@
|
||||
# `format_table`
|
||||
|
||||
Format tables with a stupid API. [Documentation](https://docs.rs/format_table).
|
||||
|
||||
Example:
|
||||
|
||||
```rust
|
||||
let mut table = vec!["product\tquantity\tprice".to_string()];
|
||||
for (p, q, r) in [("tomato", 12, 15), ("potato", 10, 20), ("rice", 5, 12)] {
|
||||
table.push(format!("{}\t{}\t{}", p, q, r));
|
||||
}
|
||||
format_table::format_table(table);
|
||||
```
|
||||
@@ -1,3 +1,19 @@
|
||||
//! Format tables with a stupid API.
|
||||
//!
|
||||
//! Example:
|
||||
//!
|
||||
//! ```rust
|
||||
//! let mut table = vec!["product\tquantity\tprice".to_string()];
|
||||
//! for (p, q, r) in [("tomato", 12, 15), ("potato", 10, 20), ("rice", 5, 12)] {
|
||||
//! table.push(format!("{}\t{}\t{}", p, q, r));
|
||||
//! }
|
||||
//! format_table::format_table(table);
|
||||
//! ```
|
||||
//!
|
||||
//! A table to be formatted is a `Vec<String>`, containing one string per line.
|
||||
//! Table columns in each line are separated by a `\t` character.
|
||||
|
||||
/// Format a table and return the result as a string.
|
||||
pub fn format_table_to_string(data: Vec<String>) -> String {
|
||||
let data = data
|
||||
.iter()
|
||||
@@ -27,6 +43,7 @@ pub fn format_table_to_string(data: Vec<String>) -> String {
|
||||
out
|
||||
}
|
||||
|
||||
/// Format a table and print the result to stdout.
|
||||
pub fn format_table(data: Vec<String>) {
|
||||
print!("{}", format_table_to_string(data));
|
||||
}
|
||||
+11
-9
@@ -21,19 +21,20 @@ path = "tests/lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_db = { version = "0.8.2", path = "../db" }
|
||||
garage_api = { version = "0.8.2", path = "../api" }
|
||||
garage_block = { version = "0.8.2", path = "../block" }
|
||||
garage_model = { version = "0.8.2", path = "../model" }
|
||||
garage_rpc = { version = "0.8.2", path = "../rpc" }
|
||||
garage_table = { version = "0.8.2", path = "../table" }
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_web = { version = "0.8.2", path = "../web" }
|
||||
format_table.workspace = true
|
||||
garage_db.workspace = true
|
||||
garage_api.workspace = true
|
||||
garage_block.workspace = true
|
||||
garage_model.workspace = true
|
||||
garage_rpc.workspace = true
|
||||
garage_table.workspace = true
|
||||
garage_util.workspace = true
|
||||
garage_web.workspace = true
|
||||
|
||||
backtrace = "0.3"
|
||||
bytes = "1.0"
|
||||
bytesize = "1.1"
|
||||
timeago = "0.4"
|
||||
timeago = { version = "0.4", default-features = false }
|
||||
parse_duration = "2.1"
|
||||
hex = "0.4"
|
||||
tracing = { version = "0.1" }
|
||||
@@ -41,6 +42,7 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
rand = "0.8"
|
||||
async-trait = "0.1.7"
|
||||
sodiumoxide = { version = "0.2.5-0", package = "kuska-sodiumoxide" }
|
||||
git-version = "0.3.4"
|
||||
|
||||
serde = { version = "1.0", default-features = false, features = ["derive", "rc"] }
|
||||
serde_bytes = "0.11"
|
||||
|
||||
+1
-1
@@ -5,11 +5,11 @@ use std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use format_table::format_table_to_string;
|
||||
use garage_util::background::BackgroundRunner;
|
||||
use garage_util::crdt::*;
|
||||
use garage_util::data::*;
|
||||
use garage_util::error::Error as GarageError;
|
||||
use garage_util::formater::format_table_to_string;
|
||||
use garage_util::time::*;
|
||||
|
||||
use garage_table::replication::*;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::collections::HashSet;
|
||||
use std::time::Duration;
|
||||
|
||||
use format_table::format_table;
|
||||
use garage_util::error::*;
|
||||
use garage_util::formater::format_table;
|
||||
|
||||
use garage_rpc::layout::*;
|
||||
use garage_rpc::system::*;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use format_table::format_table;
|
||||
use garage_util::crdt::Crdt;
|
||||
use garage_util::error::*;
|
||||
use garage_util::formater::format_table;
|
||||
|
||||
use garage_rpc::layout::*;
|
||||
use garage_rpc::system::*;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use format_table::format_table;
|
||||
use garage_util::background::*;
|
||||
use garage_util::crdt::*;
|
||||
use garage_util::data::*;
|
||||
use garage_util::error::*;
|
||||
use garage_util::formater::format_table;
|
||||
use garage_util::time::*;
|
||||
|
||||
use garage_block::manager::BlockResyncErrorInfo;
|
||||
|
||||
@@ -108,6 +108,12 @@ async fn main() {
|
||||
][..];
|
||||
if let Some(git_version) = option_env!("GIT_VERSION") {
|
||||
garage_util::version::init_version(git_version);
|
||||
} else {
|
||||
garage_util::version::init_version(git_version::git_version!(
|
||||
prefix = "git:",
|
||||
cargo_prefix = "cargo:",
|
||||
fallback = "unknown"
|
||||
));
|
||||
}
|
||||
garage_util::version::init_features(features);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "k2v-client"
|
||||
version = "0.1.1"
|
||||
version = "0.0.2"
|
||||
authors = ["Trinity Pointard <trinity.pointard@gmail.com>", "Alex Auvolat <alex@adnab.me>"]
|
||||
edition = "2018"
|
||||
license = "AGPL-3.0"
|
||||
@@ -19,15 +19,15 @@ hyper-rustls = { version = "0.23", default-features = false, features = [ "http1
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
thiserror = "1.0"
|
||||
tokio = "1.24"
|
||||
tokio = { version = "1.0", default-features = false, features = ["rt", "rt-multi-thread", "io-util", "net", "time", "macros", "sync", "signal", "fs"] }
|
||||
|
||||
# cli deps
|
||||
clap = { version = "4.1", optional = true, features = ["derive", "env"] }
|
||||
garage_util = { version = "0.8.2", path = "../util", optional = true }
|
||||
format_table = { workspace = true, optional = true }
|
||||
|
||||
|
||||
[features]
|
||||
cli = ["clap", "tokio/fs", "tokio/io-std", "garage_util"]
|
||||
cli = ["clap", "tokio/fs", "tokio/io-std", "format_table"]
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
@@ -2,9 +2,11 @@ use std::collections::BTreeMap;
|
||||
use std::process::exit;
|
||||
use std::time::Duration;
|
||||
|
||||
use base64::prelude::*;
|
||||
|
||||
use k2v_client::*;
|
||||
|
||||
use garage_util::formater::format_table;
|
||||
use format_table::format_table;
|
||||
|
||||
use rusoto_core::credential::AwsCredentials;
|
||||
use rusoto_core::Region;
|
||||
@@ -155,7 +157,9 @@ impl Value {
|
||||
if let Some(ref text) = self.text {
|
||||
Ok(text.as_bytes().to_vec())
|
||||
} else if let Some(ref b64) = self.b64 {
|
||||
base64::decode(b64).map_err(|_| Error::Message("invalid base64 input".into()))
|
||||
BASE64_STANDARD
|
||||
.decode(b64)
|
||||
.map_err(|_| Error::Message("invalid base64 input".into()))
|
||||
} else if let Some(ref path) = self.file {
|
||||
use tokio::io::AsyncReadExt;
|
||||
if path == "-" {
|
||||
@@ -230,7 +234,7 @@ impl ReadOutputKind {
|
||||
for val in val.value {
|
||||
match val {
|
||||
K2vValue::Value(v) => {
|
||||
println!("{}", base64::encode(&v))
|
||||
println!("{}", BASE64_STANDARD.encode(&v))
|
||||
}
|
||||
K2vValue::Tombstone => {
|
||||
println!();
|
||||
@@ -249,7 +253,7 @@ impl ReadOutputKind {
|
||||
if let Ok(string) = std::str::from_utf8(&v) {
|
||||
println!(" utf-8: {}", string);
|
||||
} else {
|
||||
println!(" base64: {}", base64::encode(&v));
|
||||
println!(" base64: {}", BASE64_STANDARD.encode(&v));
|
||||
}
|
||||
}
|
||||
K2vValue::Tombstone => {
|
||||
@@ -275,7 +279,7 @@ struct BatchOutputKind {
|
||||
impl BatchOutputKind {
|
||||
fn display_human_output(&self, values: BTreeMap<String, CausalValue>) -> ! {
|
||||
for (key, values) in values {
|
||||
println!("key: {}", key);
|
||||
println!("sort_key: {}", key);
|
||||
let causality: String = values.causality.into();
|
||||
println!("causality: {}", causality);
|
||||
for value in values.value {
|
||||
@@ -284,7 +288,7 @@ impl BatchOutputKind {
|
||||
if let Ok(string) = std::str::from_utf8(&v) {
|
||||
println!(" value(utf-8): {}", string);
|
||||
} else {
|
||||
println!(" value(base64): {}", base64::encode(&v));
|
||||
println!(" value(base64): {}", BASE64_STANDARD.encode(&v));
|
||||
}
|
||||
}
|
||||
K2vValue::Tombstone => {
|
||||
@@ -520,7 +524,7 @@ async fn main() -> Result<(), Error> {
|
||||
value
|
||||
.as_object_mut()
|
||||
.unwrap()
|
||||
.insert("sort_key".to_owned(), k.into());
|
||||
.insert("partition_key".to_owned(), k.into());
|
||||
value
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@@ -537,7 +541,7 @@ async fn main() -> Result<(), Error> {
|
||||
}
|
||||
|
||||
let mut to_print = Vec::new();
|
||||
to_print.push(format!("key:\tentries\tconflicts\tvalues\tbytes"));
|
||||
to_print.push(format!("partition_key\tentries\tconflicts\tvalues\tbytes"));
|
||||
for (k, v) in res.items {
|
||||
to_print.push(format!(
|
||||
"{}\t{}\t{}\t{}\t{}",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use base64::prelude::*;
|
||||
use http::header::{ACCEPT, CONTENT_LENGTH, CONTENT_TYPE};
|
||||
use http::status::StatusCode;
|
||||
use http::HeaderMap;
|
||||
@@ -375,7 +376,7 @@ impl K2vClient {
|
||||
.unwrap_or_default();
|
||||
let err_body_str = std::str::from_utf8(&err_body)
|
||||
.map(String::from)
|
||||
.unwrap_or_else(|_| base64::encode(&err_body));
|
||||
.unwrap_or_else(|_| BASE64_STANDARD.encode(&err_body));
|
||||
|
||||
if s.is_client_error() || s.is_server_error() {
|
||||
error!("Error response {}: {}", res.status, err_body_str);
|
||||
@@ -408,7 +409,7 @@ impl K2vClient {
|
||||
"Response body: {}",
|
||||
std::str::from_utf8(&body)
|
||||
.map(String::from)
|
||||
.unwrap_or_else(|_| base64::encode(&body))
|
||||
.unwrap_or_else(|_| BASE64_STANDARD.encode(&body))
|
||||
);
|
||||
|
||||
Ok(Response {
|
||||
@@ -482,9 +483,11 @@ impl<'de> Deserialize<'de> for K2vValue {
|
||||
{
|
||||
let val: Option<&str> = Option::deserialize(d)?;
|
||||
Ok(match val {
|
||||
Some(s) => {
|
||||
K2vValue::Value(base64::decode(s).map_err(|_| DeError::custom("invalid base64"))?)
|
||||
}
|
||||
Some(s) => K2vValue::Value(
|
||||
BASE64_STANDARD
|
||||
.decode(s)
|
||||
.map_err(|_| DeError::custom("invalid base64"))?,
|
||||
),
|
||||
None => K2vValue::Tombstone,
|
||||
})
|
||||
}
|
||||
@@ -498,7 +501,7 @@ impl Serialize for K2vValue {
|
||||
match self {
|
||||
K2vValue::Tombstone => serializer.serialize_none(),
|
||||
K2vValue::Value(v) => {
|
||||
let b64 = base64::encode(v);
|
||||
let b64 = BASE64_STANDARD.encode(v);
|
||||
serializer.serialize_str(&b64)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_db = { version = "0.8.2", default-features = false, path = "../db" }
|
||||
garage_rpc = { version = "0.8.2", path = "../rpc" }
|
||||
garage_table = { version = "0.8.2", path = "../table" }
|
||||
garage_block = { version = "0.8.2", path = "../block" }
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_db.workspace = true
|
||||
garage_rpc.workspace = true
|
||||
garage_table.workspace = true
|
||||
garage_block.workspace = true
|
||||
garage_util.workspace = true
|
||||
|
||||
async-trait = "0.1.7"
|
||||
arc-swap = "1.0"
|
||||
|
||||
@@ -57,56 +57,8 @@ mod v08 {
|
||||
pub struct WebsiteConfig {
|
||||
pub index_document: String,
|
||||
pub error_document: Option<String>,
|
||||
pub redirect_all_requests_to: Option<RedirectTarget>,
|
||||
pub routing_rules: Vec<RoutingRule>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RedirectTarget {
|
||||
/// Name of the host where requests are redirected.
|
||||
pub hostname: String,
|
||||
/// Protocol to use when redirecting requests. The default is the protocol that is used in the original request.
|
||||
/// Valid Values: http | https
|
||||
pub protocol: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RoutingRule {
|
||||
/// A container for describing a condition that must be met for the specified redirect to apply. For example, 1. If request is for pages in the /docs folder, redirect to the /documents folder. 2. If request results in HTTP error 4xx, redirect request to another host where you might process the error.
|
||||
pub condition: Option<RoutingCondition>,
|
||||
/// Container for redirect information. You can redirect requests to another host, to another page, or with another protocol. In the event of an error, you can specify a different error code to return.
|
||||
pub redirect: RedirectRule,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RoutingCondition {
|
||||
/// The HTTP error code when the redirect is applied. In the event of an error, if the error code equals this value, then the specified redirect is applied. Required when parent element Condition is specified and sibling KeyPrefixEquals is not specified. If both are specified, then both must be true for the redirect to be applied.
|
||||
pub http_error_code_returned_equals: Option<u16>,
|
||||
/// The object key name prefix when the redirect is applied. For example, to redirect requests for ExamplePage.html, the key prefix will be ExamplePage.html. To redirect request for all pages with the prefix docs/, the key prefix will be /docs, which identifies all objects in the docs/ folder. Required when the parent element Condition is specified and sibling HttpErrorCodeReturnedEquals is not specified. If both conditions are specified, both must be true for the redirect to be applied.
|
||||
pub key_prefix_equals: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RedirectRule {
|
||||
/// The hostname to use in the redirect request.
|
||||
pub hostname: Option<String>,
|
||||
|
||||
/// The HTTP redirect code to use on the response. Not required if one of the siblings is present.
|
||||
pub http_redirect_code: Option<u16>,
|
||||
|
||||
/// Protocol to use when redirecting requests. The default is the protocol that is used in the original request.
|
||||
/// Valid Values: http | https
|
||||
pub protocol: Option<String>,
|
||||
|
||||
/// The object key prefix to use in the redirect request. For example, to redirect requests for all pages with prefix docs/ (objects in the docs/ folder) to documents/, you can set a condition block with KeyPrefixEquals set to docs/ and in the Redirect set ReplaceKeyPrefixWith to /documents. Not required if one of the siblings is present. Can be present only if ReplaceKeyWith is not provided.
|
||||
pub replace_key_prefix_with: Option<String>,
|
||||
|
||||
/// The specific object key to use in the redirect request. For example, redirect request to error.html. Not required if one of the siblings is present. Can be present only if ReplaceKeyPrefixWith is not provided.
|
||||
pub replace_key_with: Option<String>,
|
||||
|
||||
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct CorsRule {
|
||||
pub id: Option<String>,
|
||||
|
||||
@@ -79,7 +79,7 @@ impl RangeSeenMarker {
|
||||
|
||||
let bytes = nonversioned_encode(&self)?;
|
||||
let bytes = zstd::stream::encode_all(&mut &bytes[..], zstd::DEFAULT_COMPRESSION_LEVEL)?;
|
||||
Ok(BASE64_STANDARD.encode(&bytes))
|
||||
Ok(BASE64_STANDARD.encode(bytes))
|
||||
}
|
||||
|
||||
/// Decode from msgpack+zstd+b64 representation, returns None on error.
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_util.workspace = true
|
||||
|
||||
arc-swap = "1.0"
|
||||
bytes = "1.0"
|
||||
|
||||
@@ -14,9 +14,9 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_db = { version = "0.8.2", path = "../db" }
|
||||
garage_rpc = { version = "0.8.2", path = "../rpc" }
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_db.workspace = true
|
||||
garage_rpc.workspace = true
|
||||
garage_util.workspace = true
|
||||
|
||||
opentelemetry = "0.17"
|
||||
|
||||
|
||||
+8
-8
@@ -44,22 +44,22 @@ pub struct TableData<F: TableSchema, R: TableReplication> {
|
||||
impl<F: TableSchema, R: TableReplication> TableData<F, R> {
|
||||
pub fn new(system: Arc<System>, instance: F, replication: R, db: &db::Db) -> Arc<Self> {
|
||||
let store = db
|
||||
.open_tree(&format!("{}:table", F::TABLE_NAME))
|
||||
.open_tree(format!("{}:table", F::TABLE_NAME))
|
||||
.expect("Unable to open DB tree");
|
||||
|
||||
let merkle_tree = db
|
||||
.open_tree(&format!("{}:merkle_tree", F::TABLE_NAME))
|
||||
.open_tree(format!("{}:merkle_tree", F::TABLE_NAME))
|
||||
.expect("Unable to open DB Merkle tree tree");
|
||||
let merkle_todo = db
|
||||
.open_tree(&format!("{}:merkle_todo", F::TABLE_NAME))
|
||||
.open_tree(format!("{}:merkle_todo", F::TABLE_NAME))
|
||||
.expect("Unable to open DB Merkle TODO tree");
|
||||
|
||||
let insert_queue = db
|
||||
.open_tree(&format!("{}:insert_queue", F::TABLE_NAME))
|
||||
.open_tree(format!("{}:insert_queue", F::TABLE_NAME))
|
||||
.expect("Unable to open insert queue DB tree");
|
||||
|
||||
let gc_todo = db
|
||||
.open_tree(&format!("{}:gc_todo_v2", F::TABLE_NAME))
|
||||
.open_tree(format!("{}:gc_todo_v2", F::TABLE_NAME))
|
||||
.expect("Unable to open GC DB tree");
|
||||
let gc_todo = CountedTree::new(gc_todo).expect("Cannot count gc_todo_v2");
|
||||
|
||||
@@ -90,7 +90,7 @@ impl<F: TableSchema, R: TableReplication> TableData<F, R> {
|
||||
|
||||
pub fn read_entry(&self, p: &F::P, s: &F::S) -> Result<Option<ByteBuf>, Error> {
|
||||
let tree_key = self.tree_key(p, s);
|
||||
if let Some(bytes) = self.store.get(&tree_key)? {
|
||||
if let Some(bytes) = self.store.get(tree_key)? {
|
||||
Ok(Some(ByteBuf::from(bytes.to_vec())))
|
||||
} else {
|
||||
Ok(None)
|
||||
@@ -132,10 +132,10 @@ impl<F: TableSchema, R: TableReplication> TableData<F, R> {
|
||||
}
|
||||
}
|
||||
|
||||
fn read_range_aux<'a>(
|
||||
fn read_range_aux(
|
||||
&self,
|
||||
partition_hash: Hash,
|
||||
range: db::ValueIter<'a>,
|
||||
range: db::ValueIter,
|
||||
filter: &Option<F::Filter>,
|
||||
limit: usize,
|
||||
) -> Result<Vec<Arc<ByteBuf>>, Error> {
|
||||
|
||||
+2
-7
@@ -34,8 +34,9 @@ impl DeletedFilter {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum EnumerationOrder {
|
||||
#[default]
|
||||
Forward,
|
||||
Reverse,
|
||||
}
|
||||
@@ -49,9 +50,3 @@ impl EnumerationOrder {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EnumerationOrder {
|
||||
fn default() -> Self {
|
||||
EnumerationOrder::Forward
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -14,7 +14,7 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_db = { version = "0.8.2", path = "../db" }
|
||||
garage_db.workspace = true
|
||||
|
||||
arc-swap = "1.0"
|
||||
async-trait = "0.1"
|
||||
@@ -22,7 +22,6 @@ blake2 = "0.10"
|
||||
bytes = "1.0"
|
||||
digest = "0.10"
|
||||
err-derive = "0.3"
|
||||
git-version = "0.3.4"
|
||||
hexdump = "0.1"
|
||||
xxhash-rust = { version = "0.8", default-features = false, features = ["xxh3"] }
|
||||
hex = "0.4"
|
||||
|
||||
+1
-1
@@ -223,7 +223,7 @@ fn secret_from_file(
|
||||
#[cfg(unix)]
|
||||
if std::env::var("GARAGE_ALLOW_WORLD_READABLE_SECRETS").as_deref() != Ok("true") {
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
let metadata = std::fs::metadata(&file_path)?;
|
||||
let metadata = std::fs::metadata(file_path)?;
|
||||
if metadata.mode() & 0o077 != 0 {
|
||||
return Err(format!("File {} is world-readable! (mode: 0{:o}, expected 0600)\nRefusing to start until this is fixed, or environment variable GARAGE_ALLOW_WORLD_READABLE_SECRETS is set to true.", file_path, metadata.mode()).into());
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ pub fn handle_forwarded_for_headers(headers: &HeaderMap<HeaderValue>) -> Result<
|
||||
.to_str()
|
||||
.ok_or_message("Error parsing X-Forwarded-For header")?;
|
||||
|
||||
let client_ip = IpAddr::from_str(&forwarded_for_ip_str)
|
||||
let client_ip = IpAddr::from_str(forwarded_for_ip_str)
|
||||
.ok_or_message("Valid IP address not found in X-Forwarded-For header")?;
|
||||
|
||||
Ok(client_ip.to_string())
|
||||
|
||||
@@ -10,7 +10,6 @@ pub mod crdt;
|
||||
pub mod data;
|
||||
pub mod encode;
|
||||
pub mod error;
|
||||
pub mod formater;
|
||||
pub mod forwarded_headers;
|
||||
pub mod metrics;
|
||||
pub mod migrate;
|
||||
|
||||
+4
-8
@@ -1,18 +1,14 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use arc_swap::{ArcSwap, ArcSwapOption};
|
||||
use arc_swap::ArcSwapOption;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref VERSION: ArcSwap<&'static str> = ArcSwap::new(Arc::new(git_version::git_version!(
|
||||
prefix = "git:",
|
||||
cargo_prefix = "cargo:",
|
||||
fallback = "unknown"
|
||||
)));
|
||||
static ref VERSION: ArcSwapOption<&'static str> = ArcSwapOption::new(None);
|
||||
static ref FEATURES: ArcSwapOption<&'static [&'static str]> = ArcSwapOption::new(None);
|
||||
}
|
||||
|
||||
pub fn garage_version() -> &'static str {
|
||||
&VERSION.load()
|
||||
VERSION.load().as_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn garage_features() -> Option<&'static [&'static str]> {
|
||||
@@ -20,7 +16,7 @@ pub fn garage_features() -> Option<&'static [&'static str]> {
|
||||
}
|
||||
|
||||
pub fn init_version(version: &'static str) {
|
||||
VERSION.store(Arc::new(version));
|
||||
VERSION.store(Some(Arc::new(version)));
|
||||
}
|
||||
|
||||
pub fn init_features(features: &'static [&'static str]) {
|
||||
|
||||
+4
-4
@@ -14,10 +14,10 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_api = { version = "0.8.2", path = "../api" }
|
||||
garage_model = { version = "0.8.2", path = "../model" }
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_table = { version = "0.8.2", path = "../table" }
|
||||
garage_api.workspace = true
|
||||
garage_model.workspace = true
|
||||
garage_util.workspace = true
|
||||
garage_table.workspace = true
|
||||
|
||||
err-derive = "0.3"
|
||||
tracing = "0.1"
|
||||
|
||||
@@ -106,7 +106,7 @@ impl WebServer {
|
||||
addr: SocketAddr,
|
||||
) -> Result<Response<Body>, Infallible> {
|
||||
if let Ok(forwarded_for_ip_addr) =
|
||||
forwarded_headers::handle_forwarded_for_headers(&req.headers())
|
||||
forwarded_headers::handle_forwarded_for_headers(req.headers())
|
||||
{
|
||||
info!(
|
||||
"{} (via {}) {} {}",
|
||||
|
||||
Reference in New Issue
Block a user