@@ -408,8 +408,9 @@ func findExplicitInode(ctx context.Context, bucket *gcsx.SyncerBucket, name Name
408408 return nil , fmt .Errorf ("StatObject: %w" , err )
409409 }
410410
411- // This should be treated as an implicit directory, as implicit objects do not possess metadata.
412- // We are setting MinObject to nil because, for implicit directories, only the object name is saved.
411+ // Treat this as an implicit directory. Since implicit objects lack metadata
412+ // (only the name is preserved), we set MinObject to nil. This ensures the
413+ // inode is correctly assigned the ImplicitDir Core Type.
413414 if fetchOnlyFromCache && m .Generation == 0 {
414415 m = nil
415416 }
@@ -596,12 +597,69 @@ func (d *dirInode) LookUpChild(ctx context.Context, name string) (*Core, error)
596597 return d .lookUpConflicting (ctx , name )
597598 }
598599
600+ cachedType := metadata .UnknownType
601+
602+ // 1. Optimization: If Type Cache is deprecated, attempt a lookup via the Stat Cache first.
603+ // We skip this if the metadata cache TTL is 0, as the cache layer is inactive.
604+ if d .IsTypeCacheDeprecated () && d .metadataCacheTtlSecs != 0 {
605+ var cacheMissErr * caching.CacheMissError
606+
607+ // Try File
608+ fileResult , err := findExplicitInode (ctx , d .Bucket (), NewFileName (d .Name (), name ), true )
609+ if err != nil && ! errors .As (err , & cacheMissErr ) {
610+ return nil , err
611+ }
612+
613+ // Try Directory
614+ var dirResult * Core
615+ if d .Bucket ().BucketType ().Hierarchical {
616+ dirResult , err = findExplicitFolder (ctx , d .Bucket (), NewDirName (d .Name (), name ), true )
617+ } else {
618+ dirResult , err = findExplicitInode (ctx , d .Bucket (), NewDirName (d .Name (), name ), true )
619+ }
620+ if err != nil && ! errors .As (err , & cacheMissErr ) {
621+ return nil , err
622+ }
623+
624+ if dirResult != nil {
625+ return dirResult , nil
626+ } else if fileResult != nil {
627+ return fileResult , nil
628+ }
629+ }
630+
631+ // 2. Legacy: If Type Cache is NOT deprecated, fetch the type hint.
632+ if ! d .IsTypeCacheDeprecated () {
633+ cachedType = d .cache .Get (d .cacheClock .Now (), name )
634+ }
635+
636+ // 3. Main Lookup Logic (Unified)
637+ result , err := d .fetchCoreEntity (ctx , name , cachedType )
638+ if err != nil {
639+ return nil , err
640+ }
641+
642+ // 4. Legacy: Update Type Cache if needed.
643+ if ! d .IsTypeCacheDeprecated () {
644+ if result != nil {
645+ d .cache .Insert (d .cacheClock .Now (), name , result .Type ())
646+ } else if d .enableNonexistentTypeCache && cachedType == metadata .UnknownType {
647+ d .cache .Insert (d .cacheClock .Now (), name , metadata .NonexistentType )
648+ }
649+ }
650+
651+ return result , nil
652+ }
653+
654+ // fetchCoreEntity contains all the existing logic for looking up children
655+ // without worrying about the isTypeCacheDeprecated flag.
656+ func (d * dirInode ) fetchCoreEntity (ctx context.Context , name string , cachedType metadata.Type ) (* Core , error ) {
599657 group , ctx := errgroup .WithContext (ctx )
600658
601659 var fileResult * Core
602660 var dirResult * Core
603661 var err error
604- var result * Core
662+
605663 lookUpFile := func () (err error ) {
606664 fileResult , err = findExplicitInode (ctx , d .Bucket (), NewFileName (d .Name (), name ), false )
607665 return
@@ -619,35 +677,30 @@ func (d *dirInode) LookUpChild(ctx context.Context, name string) (*Core, error)
619677 return
620678 }
621679
622- var cachedType metadata.Type
623- var cacheMissErr * caching.CacheMissError
624- if d .IsTypeCacheDeprecated () {
625- // If metadata caching is enabled, attempt to retrieve the entry from the cache first.
626- // If a valid entry (file or directory) is found, return it immediately to avoid a GCS API call.
627- if d .metadataCacheTtlSecs != 0 {
628- fileResult , err = findExplicitInode (ctx , d .Bucket (), NewFileName (d .Name (), name ), true )
629- if err != nil && ! errors .As (err , & cacheMissErr ) {
630- return nil , err
631- }
680+ switch cachedType {
681+ case metadata .ImplicitDirType :
682+ return & Core {
683+ Bucket : d .Bucket (),
684+ FullName : NewDirName (d .Name (), name ),
685+ MinObject : nil ,
686+ }, nil
632687
633- if d .Bucket ().BucketType ().Hierarchical {
634- dirResult , err = findExplicitFolder (ctx , d .Bucket (), NewDirName (d .Name (), name ), true )
635- } else {
636- dirResult , err = findExplicitInode (ctx , d .Bucket (), NewDirName (d .Name (), name ), true )
637- }
638- if err != nil && ! errors .As (err , & cacheMissErr ) {
639- return nil , err
640- }
641- if dirResult != nil {
642- result = dirResult
643- } else if fileResult != nil {
644- result = fileResult
645- }
646- if result != nil {
647- return result , nil
648- }
688+ case metadata .ExplicitDirType :
689+ if d .isBucketHierarchical () {
690+ group .Go (lookUpHNSDir )
691+ } else {
692+ group .Go (lookUpExplicitDir )
649693 }
650694
695+ case metadata .RegularFileType , metadata .SymlinkType :
696+ group .Go (lookUpFile )
697+
698+ case metadata .NonexistentType :
699+ return nil , nil
700+
701+ case metadata .UnknownType :
702+ // Entry not present in cache or cache is deprecated.
703+ // Trigger prefetcher
651704 d .prefetcher .Run (NewFileName (d .Name (), name ).GcsObjectName ())
652705
653706 group .Go (lookUpFile )
@@ -660,63 +713,16 @@ func (d *dirInode) LookUpChild(ctx context.Context, name string) (*Core, error)
660713 group .Go (lookUpExplicitDir )
661714 }
662715 }
663- } else {
664- cachedType = d .cache .Get (d .cacheClock .Now (), name )
665- switch cachedType {
666- case metadata .ImplicitDirType :
667- dirResult = & Core {
668- Bucket : d .Bucket (),
669- FullName : NewDirName (d .Name (), name ),
670- MinObject : nil ,
671- }
672- case metadata .ExplicitDirType :
673- if d .isBucketHierarchical () {
674- group .Go (lookUpHNSDir )
675- } else {
676- group .Go (lookUpExplicitDir )
677- }
678- case metadata .RegularFileType , metadata .SymlinkType :
679- group .Go (lookUpFile )
680- case metadata .NonexistentType :
681- return nil , nil
682- case metadata .UnknownType :
683- // Entry not present in cache.
684- // Trigger prefetcher
685- d .prefetcher .Run (NewFileName (d .Name (), name ).GcsObjectName ())
686-
687- group .Go (lookUpFile )
688- if d .isBucketHierarchical () {
689- group .Go (lookUpHNSDir )
690- } else {
691- if d .implicitDirs {
692- group .Go (lookUpImplicitOrExplicitDir )
693- } else {
694- group .Go (lookUpExplicitDir )
695- }
696- }
697-
698- }
699716 }
700717
701718 if err = group .Wait (); err != nil {
702719 return nil , err
703720 }
704721
705722 if dirResult != nil {
706- result = dirResult
707- } else if fileResult != nil {
708- result = fileResult
723+ return dirResult , nil
709724 }
710-
711- if ! d .IsTypeCacheDeprecated () {
712- if result != nil {
713- d .cache .Insert (d .cacheClock .Now (), name , result .Type ())
714- } else if d .enableNonexistentTypeCache && cachedType == metadata .UnknownType {
715- d .cache .Insert (d .cacheClock .Now (), name , metadata .NonexistentType )
716- }
717- }
718-
719- return result , nil
725+ return fileResult , nil
720726}
721727
722728func (d * dirInode ) IsUnlinked () bool {
0 commit comments