Example #1
0
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),
	}
}
Example #2
0
// 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
}