github.com/pbberlin/tools@v0.0.0-20160910141205-7aa5421c2169/os/fsi/dsfs/low_level_dirs_query.go (about)

     1  package dsfs
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/pbberlin/tools/os/fsi"
     7  	"github.com/pbberlin/tools/os/fsi/common"
     8  
     9  	"google.golang.org/appengine/datastore"
    10  	aelog "google.golang.org/appengine/log"
    11  )
    12  
    13  // subtreeByPath retrieves a subdirectories of a given directory.
    14  // It is relying on an indexed string property "Dir"
    15  // containing a string representation of the full path.
    16  //
    17  // It might be fast for deep, uncached directory subtree,
    18  // that have been saved in nested manner.
    19  //
    20  // However, it might not find recently added directories.
    21  // Upon finding nothing, it therefore returns the
    22  // "warning" fsi.EmptyQueryResult
    23  //
    24  // The func could easily be enhanced chunked scanning.
    25  //
    26  // It is currently used by ReadDir and by the test package.
    27  // It is public for the test package.
    28  func (fs *dsFileSys) SubtreeByPath(name string, onlyDirectChildren bool) ([]DsDir, error) {
    29  
    30  	dir, bname := fs.SplitX(name)
    31  	name = dir + common.Filify(bname)
    32  	if !strings.HasSuffix(name, sep) {
    33  		name += sep
    34  	}
    35  
    36  	var q *datastore.Query
    37  
    38  	if onlyDirectChildren {
    39  		q = datastore.NewQuery(tdir).
    40  			Filter("Dir=", name).
    41  			Order("Dir")
    42  		//  Limit(4)
    43  	} else {
    44  		pathInc := IncrementString(name)
    45  		q = datastore.NewQuery(tdir).
    46  			Filter("Dir>=", name).
    47  			Filter("Dir<", pathInc).
    48  			Order("Dir")
    49  	}
    50  
    51  	// log.Printf("%v", q)
    52  
    53  	var children []DsDir
    54  	keys, err := q.GetAll(fs.Ctx(), &children)
    55  	if err != nil {
    56  		aelog.Errorf(fs.Ctx(), "Error getting all children of %v => %v", dir+bname, err)
    57  		return children, err
    58  	}
    59  
    60  	if len(children) < 1 {
    61  		return children, fsi.EmptyQueryResult
    62  	}
    63  
    64  	// Very evil: We filter out root node, since it's
    65  	// has the same dir as the level-1 directories.
    66  	keyRoot := datastore.NewKey(fs.Ctx(), tdir, fs.RootDir(), 0, nil)
    67  	idxRoot := -1
    68  
    69  	for i := 0; i < len(children); i++ {
    70  		children[i].fSys = fs
    71  		children[i].Key = keys[i]
    72  		if keys[i].Equal(keyRoot) {
    73  			// log.Printf("root idx %v", i)
    74  			idxRoot = i
    75  		}
    76  	}
    77  
    78  	if idxRoot > -1 {
    79  		children = append(children[:idxRoot], children[idxRoot+1:]...)
    80  	}
    81  
    82  	return children, nil
    83  
    84  }