func NewCache(path string, client *http.Client) Reader { return &driveCache{ path: path, client: client, chunkSize: *chunkSize, lru: lru.New(int(*numChunks)), pending: make(map[chunk]*readRequest), } }
// NewDriveDB creates a new DriveDB and starts syncing metadata. func NewDriveDB(client *http.Client, dbPath, cachePath string, pollInterval time.Duration, rootId string) (*DriveDB, error) { svc, _ := gdrive.New(client) _, err := svc.About.Get().Do() if err != nil { log.Fatalf("drive.service.About.Get().Do: %v\n", err) } if *debugDriveDB { debug = true } ldbPath := path.Join(dbPath, "meta") log.Printf("using db path: %q", ldbPath) err = os.MkdirAll(ldbPath, 0700) if err != nil { return nil, fmt.Errorf("could not create directory %q", ldbPath) } log.Printf("using cache path: %q", cachePath) err = os.MkdirAll(cachePath, 0700) if err != nil { return nil, fmt.Errorf("could not create directory %q", cachePath) } db, err := openLevelDB(ldbPath) if err != nil { return nil, err } d := &DriveDB{ client: client, service: svc, db: db, dbpath: ldbPath, data: cachePath, lruCache: lru.New(*inodeCacheSize), changes: make(chan *gdrive.ChangeList, 200), pollInterval: pollInterval, rootId: rootId, driveSize: (*driveCacheChunk) * (*driveCacheChunks), // ensure drive reads are always a multiple of cache size cacheBlocks: (*cacheSize) * ((*driveCacheChunks) * (*prefetchMultiplier)), // enough blocks for readahead pfetchq: make(chan DownloadSpec, 20000), pfetchmap: make(map[string]bool), } log.Printf("%d cache blocks of %d bytes", d.cacheBlocks, *driveCacheChunk) // Get saved checkpoint. err = d.get(internalKey("checkpoint"), &d.cpt) if err != nil { log.Printf("error reading checkpoint: %v", err) d.cpt = NewCheckpoint() } if d.cpt.Version != checkpointVersion { log.Printf("checkpoint version invalid, require %v but found %v", checkpointVersion, d.cpt.Version) err = d.reinit() if err != nil { log.Printf("Failed to reinitialize the database: %v", err) log.Fatal("You should probably run: rm -rf %v", ldbPath) } } err = d.writeCheckpoint(nil) if err != nil { return nil, fmt.Errorf("could not write checkpoint: %v", err) } debug.Printf("Recovered from checkpoint: %+v", d.cpt) if err := d.createRoot(); err != nil { return nil, fmt.Errorf("could not create root inode entry: %v", err) } d.synced = sync.NewCond(&d.syncmu) go d.sync() go d.pollForChanges() if debug { registerDebugHandles(*d) // in http_handlers.go } for i := 0; i < *prefetchWorkers; i++ { go d.prefetcher() } return d, nil }