mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-17 03:50:51 +02:00
ensure .versions directory exists
This commit is contained in:
@@ -636,11 +636,25 @@ func (s3a *S3ApiServer) updateLatestVersionInDirectory(bucket, object, versionId
|
||||
bucketDir := s3a.option.BucketsPath + "/" + bucket
|
||||
versionsObjectPath := object + ".versions"
|
||||
|
||||
// Get the current .versions directory entry
|
||||
// Get the current .versions directory entry, create if it doesn't exist
|
||||
versionsEntry, err := s3a.getEntry(bucketDir, versionsObjectPath)
|
||||
if err != nil {
|
||||
glog.Errorf("updateLatestVersionInDirectory: failed to get .versions entry: %v", err)
|
||||
return fmt.Errorf("failed to get .versions entry: %w", err)
|
||||
glog.V(2).Infof("updateLatestVersionInDirectory: .versions directory doesn't exist for %s/%s, creating it", bucket, object)
|
||||
// Create the .versions directory if it doesn't exist
|
||||
err = s3a.mkdir(bucketDir, versionsObjectPath, func(entry *filer_pb.Entry) {
|
||||
entry.Attributes.Mime = s3_constants.FolderMimeType
|
||||
if entry.Extended == nil {
|
||||
entry.Extended = make(map[string][]byte)
|
||||
}
|
||||
entry.Extended[s3_constants.ExtLatestVersionIdKey] = []byte(versionId)
|
||||
entry.Extended[s3_constants.ExtLatestVersionFileNameKey] = []byte(versionFileName)
|
||||
})
|
||||
if err != nil {
|
||||
glog.Errorf("updateLatestVersionInDirectory: failed to create .versions directory: %v", err)
|
||||
return fmt.Errorf("failed to create .versions directory: %w", err)
|
||||
}
|
||||
glog.V(2).Infof("updateLatestVersionInDirectory: created .versions directory for %s/%s with version %s", bucket, object, versionId)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Add or update the latest version metadata
|
||||
|
||||
@@ -151,6 +151,8 @@ func (s3a *S3ApiServer) createDeleteMarker(bucket, object string) (string, error
|
||||
func (s3a *S3ApiServer) listObjectVersions(bucket, prefix, keyMarker, versionIdMarker, delimiter string, maxKeys int) (*S3ListObjectVersionsResult, error) {
|
||||
var allVersions []interface{} // Can contain VersionEntry or DeleteMarkerEntry
|
||||
|
||||
glog.V(1).Infof("listObjectVersions: listing versions for bucket %s, prefix '%s'", bucket, prefix)
|
||||
|
||||
// Track objects that have been processed to avoid duplicates
|
||||
processedObjects := make(map[string]bool)
|
||||
|
||||
@@ -161,9 +163,12 @@ func (s3a *S3ApiServer) listObjectVersions(bucket, prefix, keyMarker, versionIdM
|
||||
bucketPath := path.Join(s3a.option.BucketsPath, bucket)
|
||||
err := s3a.findVersionsRecursively(bucketPath, "", &allVersions, processedObjects, seenVersionIds, bucket, prefix)
|
||||
if err != nil {
|
||||
glog.Errorf("listObjectVersions: findVersionsRecursively failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
glog.V(1).Infof("listObjectVersions: found %d total versions", len(allVersions))
|
||||
|
||||
// Sort by key, then by LastModified (newest first), then by VersionId for deterministic ordering
|
||||
sort.Slice(allVersions, func(i, j int) bool {
|
||||
var keyI, keyJ string
|
||||
@@ -218,6 +223,8 @@ func (s3a *S3ApiServer) listObjectVersions(bucket, prefix, keyMarker, versionIdM
|
||||
IsTruncated: len(allVersions) > maxKeys,
|
||||
}
|
||||
|
||||
glog.V(1).Infof("listObjectVersions: building response with %d versions (truncated: %v)", len(allVersions), result.IsTruncated)
|
||||
|
||||
// Limit results
|
||||
if len(allVersions) > maxKeys {
|
||||
allVersions = allVersions[:maxKeys]
|
||||
@@ -239,15 +246,19 @@ func (s3a *S3ApiServer) listObjectVersions(bucket, prefix, keyMarker, versionIdM
|
||||
result.DeleteMarkers = make([]DeleteMarkerEntry, 0)
|
||||
|
||||
// Add versions to result
|
||||
for _, version := range allVersions {
|
||||
for i, version := range allVersions {
|
||||
switch v := version.(type) {
|
||||
case *VersionEntry:
|
||||
glog.V(2).Infof("listObjectVersions: adding version %d: key=%s, versionId=%s", i, v.Key, v.VersionId)
|
||||
result.Versions = append(result.Versions, *v)
|
||||
case *DeleteMarkerEntry:
|
||||
glog.V(2).Infof("listObjectVersions: adding delete marker %d: key=%s, versionId=%s", i, v.Key, v.VersionId)
|
||||
result.DeleteMarkers = append(result.DeleteMarkers, *v)
|
||||
}
|
||||
}
|
||||
|
||||
glog.V(1).Infof("listObjectVersions: final result - %d versions, %d delete markers", len(result.Versions), len(result.DeleteMarkers))
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -768,20 +779,23 @@ func (s3a *S3ApiServer) getLatestObjectVersion(bucket, object string) (*filer_pb
|
||||
bucketDir := s3a.option.BucketsPath + "/" + bucket
|
||||
versionsObjectPath := object + ".versions"
|
||||
|
||||
glog.V(1).Infof("getLatestObjectVersion: looking for latest version of %s/%s", bucket, object)
|
||||
|
||||
// Get the .versions directory entry to read latest version metadata
|
||||
versionsEntry, err := s3a.getEntry(bucketDir, versionsObjectPath)
|
||||
if err != nil {
|
||||
// .versions directory doesn't exist - this can happen for objects that existed
|
||||
// before versioning was enabled on the bucket. Fall back to checking for a
|
||||
// regular (non-versioned) object file.
|
||||
glog.V(2).Infof("getLatestObjectVersion: no .versions directory for %s%s, checking for pre-versioning object", bucket, object)
|
||||
glog.V(1).Infof("getLatestObjectVersion: no .versions directory for %s%s (error: %v), checking for pre-versioning object", bucket, object, err)
|
||||
|
||||
regularEntry, regularErr := s3a.getEntry(bucketDir, object)
|
||||
if regularErr != nil {
|
||||
glog.V(1).Infof("getLatestObjectVersion: no pre-versioning object found for %s%s (error: %v)", bucket, object, regularErr)
|
||||
return nil, fmt.Errorf("failed to get %s%s .versions directory and no regular object found: %w", bucket, object, err)
|
||||
}
|
||||
|
||||
glog.V(2).Infof("getLatestObjectVersion: found pre-versioning object for %s/%s", bucket, object)
|
||||
glog.V(1).Infof("getLatestObjectVersion: found pre-versioning object for %s/%s", bucket, object)
|
||||
return regularEntry, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user