drive: remove files.Info from FsObjectDrive and copy data out to save memory

This commit is contained in:
Nick Craig-Wood 2013-01-19 10:11:55 +00:00
parent f8246b5a7e
commit 98108caac2

View file

@ -1,7 +1,8 @@
// Drive interface // Drive interface
package main package main
// FIXME drive code is leaking goroutines somehow // FIXME drive code is leaking goroutines somehow - reported bug
// https://code.google.com/p/google-api-go-client/issues/detail?id=23
// FIXME use recursive listing not bound to directory for speed? // FIXME use recursive listing not bound to directory for speed?
@ -10,8 +11,6 @@ package main
// FIXME list directory should list to channel for concurrency not // FIXME list directory should list to channel for concurrency not
// append to array // append to array
// FIXME drive times only accurate to 1 ms (3 decimal places)
// FIXME perhaps have a drive setup mode where we ask for all the // FIXME perhaps have a drive setup mode where we ask for all the
// params interactively and store them all in one file // params interactively and store them all in one file
// - don't need to store client* apparently // - don't need to store client* apparently
@ -55,9 +54,13 @@ type FsDrive struct {
// FsObjectDrive describes a drive object // FsObjectDrive describes a drive object
type FsObjectDrive struct { type FsObjectDrive struct {
drive *FsDrive // what this object is part of drive *FsDrive // what this object is part of
remote string // The remote path remote string // The remote path
info *drive.File // Info from the drive object if known id string // Drive Id of this object
url string // Download URL of this object
md5sum string // md5sum of the object
bytes int64 // size of the object
modifiedDate string // RFC3339 time it was last modified
} }
// lockedMap is a map with a mutex // lockedMap is a map with a mutex
@ -257,7 +260,7 @@ func (f *FsDrive) NewFsObjectWithInfo(remote string, info *drive.File) FsObject
remote: remote, remote: remote,
} }
if info != nil { if info != nil {
fs.info = info fs.setMetaData(info)
} else { } else {
err := fs.readMetaData() // reads info and meta, returning an error err := fs.readMetaData() // reads info and meta, returning an error
if err != nil { if err != nil {
@ -498,7 +501,7 @@ func (f *FsDrive) Put(in io.Reader, remote string, modTime time.Time, size int64
if err != nil { if err != nil {
return nil, fmt.Errorf("Upload failed: %s", err) return nil, fmt.Errorf("Upload failed: %s", err)
} }
fs.info = info fs.setMetaData(info)
// Set modified date // Set modified date
info.ModifiedDate = modTime.Format(time.RFC3339Nano) info.ModifiedDate = modTime.Format(time.RFC3339Nano)
@ -571,19 +574,26 @@ func (fs *FsObjectDrive) Remote() string {
// Md5sum returns the Md5sum of an object returning a lowercase hex string // Md5sum returns the Md5sum of an object returning a lowercase hex string
func (fs *FsObjectDrive) Md5sum() (string, error) { func (fs *FsObjectDrive) Md5sum() (string, error) {
return strings.ToLower(fs.info.Md5Checksum), nil return fs.md5sum, nil
} }
// Size returns the size of an object in bytes // Size returns the size of an object in bytes
func (fs *FsObjectDrive) Size() int64 { func (fs *FsObjectDrive) Size() int64 {
return fs.info.FileSize return fs.bytes
}
// setMetaData sets the fs data from a drive.File
func (fs *FsObjectDrive) setMetaData(info *drive.File) {
fs.id = info.Id
fs.url = info.DownloadUrl
fs.md5sum = strings.ToLower(info.Md5Checksum)
fs.bytes = info.FileSize
fs.modifiedDate = info.ModifiedDate
} }
// readMetaData gets the info if it hasn't already been fetched // readMetaData gets the info if it hasn't already been fetched
//
// it also sets the info
func (fs *FsObjectDrive) readMetaData() (err error) { func (fs *FsObjectDrive) readMetaData() (err error) {
if fs.info != nil { if fs.id != "" {
return nil return nil
} }
@ -600,7 +610,7 @@ func (fs *FsObjectDrive) readMetaData() (err error) {
} }
for _, file := range items { for _, file := range items {
if file.Title == leaf { if file.Title == leaf {
fs.info = file fs.setMetaData(file)
return nil return nil
} }
} }
@ -619,7 +629,7 @@ func (fs *FsObjectDrive) ModTime() time.Time {
FsLog(fs, "Failed to read metadata: %s", err) FsLog(fs, "Failed to read metadata: %s", err)
return time.Now() return time.Now()
} }
modTime, err := time.Parse(time.RFC3339, fs.info.ModifiedDate) modTime, err := time.Parse(time.RFC3339, fs.modifiedDate)
if err != nil { if err != nil {
FsLog(fs, "Failed to read mtime from object: %s", err) FsLog(fs, "Failed to read mtime from object: %s", err)
return time.Now() return time.Now()
@ -635,9 +645,12 @@ func (fs *FsObjectDrive) SetModTime(modTime time.Time) {
FsLog(fs, "Failed to read metadata: %s", err) FsLog(fs, "Failed to read metadata: %s", err)
return return
} }
// New metadata
info := &drive.File{
ModifiedDate: modTime.Format(time.RFC3339Nano),
}
// Set modified date // Set modified date
fs.info.ModifiedDate = modTime.Format(time.RFC3339Nano) _, err = fs.drive.svc.Files.Update(fs.id, info).SetModifiedDate(true).Do()
_, err = fs.drive.svc.Files.Update(fs.info.Id, fs.info).SetModifiedDate(true).Do()
if err != nil { if err != nil {
stats.Error() stats.Error()
FsLog(fs, "Failed to update remote mtime: %s", err) FsLog(fs, "Failed to update remote mtime: %s", err)
@ -651,7 +664,7 @@ func (fs *FsObjectDrive) Storable() bool {
// Open an object for read // Open an object for read
func (fs *FsObjectDrive) Open() (in io.ReadCloser, err error) { func (fs *FsObjectDrive) Open() (in io.ReadCloser, err error) {
req, _ := http.NewRequest("GET", fs.info.DownloadUrl, nil) req, _ := http.NewRequest("GET", fs.url, nil)
req.Header.Set("User-Agent", "swiftsync/1.0") req.Header.Set("User-Agent", "swiftsync/1.0")
res, err := fs.drive.client.Do(req) res, err := fs.drive.client.Do(req)
if err != nil { if err != nil {
@ -666,7 +679,7 @@ func (fs *FsObjectDrive) Open() (in io.ReadCloser, err error) {
// Remove an object // Remove an object
func (fs *FsObjectDrive) Remove() error { func (fs *FsObjectDrive) Remove() error {
return fs.drive.svc.Files.Delete(fs.info.Id).Do() return fs.drive.svc.Files.Delete(fs.id).Do()
} }
// Check the interfaces are satisfied // Check the interfaces are satisfied