s3: fix critical path normalization inconsistency in versioned objects
ROOT CAUSE IDENTIFIED: The issue with objects like '//bar', '//testobjfoo',
'//testobjbar', and '/key' was due to inconsistent path normalization between
object upload and versioned metadata operations.
PROBLEM:
- toFilerUrl() calls removeDuplicateSlashes() normalizing '//bar' → '/bar'
- But versioned operations used raw object paths: '//bar.versions'
- This created a mismatch where version files were stored under '/bar.versions/'
but .versions directory metadata was stored under '//bar.versions'
- Filer lookups failed because paths didn't match
SOLUTION:
- Apply removeDuplicateSlashes() consistently in all versioned operations:
- putVersionedObject: normalize before creating .versions directory
- getLatestObjectVersion: normalize before looking up .versions directory
- getSpecificObjectVersion: normalize for all version operations
- deleteSpecificObjectVersion: normalize for version deletion
- Ensures all version-related paths use the same normalization as toFilerUrl()
This should resolve the persistent CI failures for objects with double slashes
in their paths, eliminating the 'filer: no entry is found in filer store' errors
that even 8 retries with exponential backoff couldn't resolve.
glog.V(0).Infof("CI-DEBUG: putVersionedObject: about to update latest version metadata for %s/%s version %s (normalized: %s)",bucket,object,versionId,normalizedObject)
glog.Errorf("putVersionedObject: failed to update latest version in directory: %v",err)
glog.V(0).Infof("CI-DEBUG: putVersionedObject: FAILED to update latest version metadata for %s/%s version %s: %v",bucket,object,versionId,err)
return"","",s3err.ErrInternalError
}
glog.V(0).Infof("CI-DEBUG: putVersionedObject: successfully updated latest version metadata for %s/%s version %s",bucket,object,versionId)
glog.V(2).Infof("putVersionedObject: successfully created version %s for %s/%s",versionId,bucket,object)
glog.V(0).Infof("CI-DEBUG: putVersionedObject: successfully updated latest version metadata for %s/%s version %s (normalized: %s)",bucket,object,versionId,normalizedObject)
glog.V(2).Infof("putVersionedObject: successfully created version %s for %s/%s (normalized: %s)",versionId,bucket,object,normalizedObject)
// .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(1).Infof("getLatestObjectVersion: no .versions directory for %s%s after %d attempts (error: %v), checking for pre-versioning object",bucket,object,maxRetries,err)
glog.V(0).Infof("CI-DEBUG: getLatestObjectVersion: no .versions directory for %s/%s after %d attempts (total delay ~%dms, error: %v), falling back to pre-versioning",bucket,object,maxRetries,(100*(1<<maxRetries-1)-100),err)
glog.V(1).Infof("getLatestObjectVersion: no .versions directory for %s%s after %d attempts (error: %v), checking for pre-versioning object",bucket,normalizedObject,maxRetries,err)
glog.V(0).Infof("CI-DEBUG: getLatestObjectVersion: no .versions directory for %s/%s after %d attempts (total delay ~%dms, error: %v), falling back to pre-versioning",bucket,normalizedObject,maxRetries,(100*(1<<maxRetries-1)-100),err)
glog.V(2).Infof("getLatestObjectVersion: no Extended metadata in .versions directory for %s%s after retries, checking for pre-versioning object",bucket,object)
glog.V(0).Infof("CI-DEBUG: getLatestObjectVersion: NO Extended metadata for %s/%s after %d retries - falling back to pre-versioning",bucket,object,metadataRetries)