Files
seaweedfs/weed/storage/store_configure_volume_test.go
T
Chris LuandDevin 867a537802 volume.configure: keep the superblock in sync with the .vif (#11930)
* volume.configure: keep the superblock in sync with the .vif

ConfigureVolume only rewrote the .vif's replication field, leaving the
.dat superblock stale. A mounted volume also kept reporting the old
placement in heartbeats, and its next compaction would rewrite the stale
placement into a fresh .dat.

Parse the placement once, then update the live volume when mounted: the
in-memory .vif copy and superblock, and the .dat header through the
volume's own backend under the data-file locks. For unmounted volumes
rewrite the header directly; remote-only volumes skip it since the .vif
carries the placement.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* volume.configure: update the .dat superblock in the Rust volume server

Mirror the Go ConfigureVolume change: after rewriting the .vif, rewrite
the replica placement in the .dat header too, so a remounted volume's
superblock, heartbeats, and later compactions agree with the .vif. A
missing .dat (remote-only volume) is skipped since the .vif carries the
placement.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-21 20:18:56 -07:00

48 lines
1.7 KiB
Go

package storage
import (
"os"
"testing"
"github.com/stretchr/testify/require"
"github.com/seaweedfs/seaweedfs/weed/stats"
"github.com/seaweedfs/seaweedfs/weed/storage/backend"
"github.com/seaweedfs/seaweedfs/weed/storage/needle"
"github.com/seaweedfs/seaweedfs/weed/storage/super_block"
"github.com/seaweedfs/seaweedfs/weed/storage/types"
"github.com/seaweedfs/seaweedfs/weed/storage/volume_info"
"github.com/seaweedfs/seaweedfs/weed/util"
)
// volume.configure must leave the live superblock, the .dat header, the
// in-memory .vif copy and the .vif on disk all on the new placement.
func TestConfigureVolumeUpdatesSuperblock(t *testing.T) {
dir := t.TempDir()
store := NewStore(nil, "localhost", 8080, 18080, "http://localhost:8080", "store-id",
[]string{dir}, []int32{10}, []util.MinFreeSpace{{}}, "", NeedleMapInMemory,
[]types.DiskType{types.HardDriveType}, nil, 0, stats.DefaultDiskIOProbeConfig())
t.Cleanup(store.Close)
require.NoError(t, store.AddVolume(1, "", NeedleMapInMemory, "000", "", 0, needle.GetCurrentVersion(), 0, types.HardDriveType, 0))
require.NoError(t, store.ConfigureVolume(1, "010"))
v := store.GetVolume(1)
require.NotNil(t, v)
require.Equal(t, "010", v.ReplicaPlacement.String())
require.Equal(t, "010", v.GetVolumeInfo().GetReplication())
datFile, err := os.Open(v.FileName(".dat"))
require.NoError(t, err)
sb, err := super_block.ReadSuperBlock(backend.NewDiskFile(datFile))
require.NoError(t, err)
datFile.Close()
require.Equal(t, "010", sb.ReplicaPlacement.String())
volumeInfo, _, _, err := volume_info.MaybeLoadVolumeInfo(v.FileName(".vif"))
require.NoError(t, err)
require.Equal(t, "010", volumeInfo.GetReplication())
require.Error(t, store.ConfigureVolume(1, "bogus"))
}