mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-11-05 19:47:47 +01:00
rust volume: mirror the VolumeConsolidateIndex RPC from Go (#10752)
The Go volume server has VolumeConsolidateIndex, which moves a volume's .idx out of the data directory into the configured -dir.idx directory (where an EC decode/reconstruct can leave it co-located) and reloads the volume in place. The Rust port's proto omitted the RPC entirely, so its generated VolumeServer trait was one method short of Go's. Add the proto message and rpc, the gated grpc handler, and Store::consolidate_volume_index / Volume::relocate_index_to, mirroring Go's Store.ConsolidateVolumeIndex and Volume.RelocateIndexTo -- including the cross-device copy fallback and the reopen-against-the-old-dir path when the move fails. Integration tests cover the real move (index relocated, volume still serves reads and the move is idempotent), the no-op paths (index already in place, no separate idx dir) and the not-found error, plus the grpc handler end to end.
This commit is contained in:
1 parent
7f27c572c4
commit
ae2cc8225e
4 files changed
+309
-1
No files matched your search
@@ -952,6 +952,22 @@ impl VolumeServer for VolumeGrpcService {
|
||||
Ok(Response::new(volume_server_pb::VolumeUnmountResponse {}))
|
||||
}
|
||||
|
||||
async fn volume_consolidate_index(
|
||||
&self,
|
||||
request: Request<volume_server_pb::VolumeConsolidateIndexRequest>,
|
||||
) -> Result<Response<volume_server_pb::VolumeConsolidateIndexResponse>, Status> {
|
||||
self.check_grpc_admin_auth(&request)?;
|
||||
self.state.check_maintenance()?;
|
||||
let vid = VolumeId(request.into_inner().volume_id);
|
||||
let mut store = self.state.store.write().unwrap();
|
||||
store
|
||||
.consolidate_volume_index(vid)
|
||||
.map_err(|e| Status::internal(e.to_string()))?;
|
||||
Ok(Response::new(
|
||||
volume_server_pb::VolumeConsolidateIndexResponse {},
|
||||
))
|
||||
}
|
||||
|
||||
async fn volume_delete(
|
||||
&self,
|
||||
request: Request<volume_server_pb::VolumeDeleteRequest>,
|
||||
@@ -5416,6 +5432,29 @@ mod tests {
|
||||
(VolumeGrpcService { state }, tmp)
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_volume_consolidate_index_rpc() {
|
||||
let (service, _tmp) = make_local_service_with_volume("consolidate_rpc", None);
|
||||
|
||||
// Carry a peer address so the admin gate sees a caller; the test guard
|
||||
// has an empty whitelist, so any peer is accepted.
|
||||
let mut request = Request::new(volume_server_pb::VolumeConsolidateIndexRequest {
|
||||
volume_id: 1,
|
||||
});
|
||||
request.extensions_mut().insert(tonic::transport::server::TcpConnectInfo {
|
||||
local_addr: None,
|
||||
remote_addr: Some("127.0.0.1:65000".parse().unwrap()),
|
||||
});
|
||||
|
||||
service.volume_consolidate_index(request).await.unwrap();
|
||||
|
||||
// Data and index share a directory here, so there is nothing to move;
|
||||
// the volume stays mounted and keeps its needle.
|
||||
let store = service.state.store.read().unwrap();
|
||||
let (_, v) = store.find_volume(VolumeId(1)).unwrap();
|
||||
assert_eq!(v.file_count(), 1);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_volume_incremental_copy_streams_remote_only_volume_data() {
|
||||
let (service, _tmp, shutdown_tx, dat_bytes, super_block_size, _delete_count) =
|
||||
|
||||
Reference in new issue
Block a user