func (t *mutableContentTest) SetUp(ti *TestInfo) { t.ctx = ti.Ctx // Set up the mock initial contents, including a default size. t.initialContent = mock_lease.NewMockReadProxy( ti.MockController, "initialContent") ExpectCall(t.initialContent, "Size")(). WillRepeatedly(Return(initialContentSize)) // Set up a mock read/write lease. t.rwl = mock_lease.NewMockReadWriteLease( ti.MockController, "rwl") // Ignore uninteresting calls. ExpectCall(t.initialContent, "CheckInvariants")(). WillRepeatedly(Return()) // Set up the clock. t.clock.SetTime(time.Date(2012, 8, 15, 22, 56, 0, 0, time.Local)) // And the mutable content. t.mc.ctx = ti.Ctx t.mc.wrapped = mutable.NewContent( t.initialContent, &t.clock) }
// Write out contents to GCS. If this fails due to the generation having been // clobbered, treat it as a non-error (simulating the inode having been // unlinked). // // After this method succeeds, SourceGeneration will return the new generation // by which this inode should be known (which may be the same as before). If it // fails, the generation will not change. // // LOCKS_REQUIRED(f.mu) func (f *FileInode) Sync(ctx context.Context) (err error) { // Write out the contents if they are dirty. rl, newObj, err := f.objectSyncer.SyncObject( ctx, &f.src, f.content) // Special case: a precondition error means we were clobbered, which we treat // as being unlinked. There's no reason to return an error in that case. if _, ok := err.(*gcs.PreconditionError); ok { err = nil } // Propagate other errors. if err != nil { err = fmt.Errorf("gcsproxy.Sync: %v", err) return } // If we wrote out a new object, we need to update our state. if newObj != nil { f.src = *newObj f.content = mutable.NewContent( gcsproxy.NewReadProxy( newObj, rl, f.gcsChunkSize, f.leaser, f.bucket), f.clock) } return }
func (t *IntegrationTest) create(o *gcs.Object) { // Set up the read proxy. rp := gcsproxy.NewReadProxy( o, nil, chunkSize, t.leaser, t.bucket) // Use it to create the mutable content. t.mc = mutable.NewContent(rp, &t.clock) }
func (t *ObjectSyncerTest) SetUp(ti *TestInfo) { var err error t.ctx = ti.Ctx // Set up dependencies. t.bucket = gcsfake.NewFakeBucket(&t.clock, "some_bucket") t.leaser = lease.NewFileLeaser("", math.MaxInt32, math.MaxInt32) t.syncer = newObjectSyncer( appendThreshold, &t.fullCreator, &t.appendCreator) t.clock.SetTime(time.Date(2015, 4, 5, 2, 15, 0, 0, time.Local)) // Set up a source object. t.srcObject, err = t.bucket.CreateObject( t.ctx, &gcs.CreateObjectRequest{ Name: "foo", Contents: strings.NewReader(srcObjectContents), }) AssertEq(nil, err) // Wrap a mutable.Content around it. t.content = mutable.NewContent( NewReadProxy( t.srcObject, nil, // Initial read lease math.MaxUint64, // Chunk size t.leaser, t.bucket), &t.clock) // Return errors from the fakes by default. t.fullCreator.err = errors.New("Fake error") t.appendCreator.err = errors.New("Fake error") }
// Create a file inode for the given object in GCS. The initial lookup count is // zero. // // gcsChunkSize controls the maximum size of each individual read request made // to GCS. // // REQUIRES: o != nil // REQUIRES: o.Generation > 0 // REQUIRES: len(o.Name) > 0 // REQUIRES: o.Name[len(o.Name)-1] != '/' func NewFileInode( id fuseops.InodeID, o *gcs.Object, attrs fuseops.InodeAttributes, gcsChunkSize uint64, bucket gcs.Bucket, leaser lease.FileLeaser, objectSyncer gcsproxy.ObjectSyncer, clock timeutil.Clock) (f *FileInode) { // Set up the basic struct. f = &FileInode{ bucket: bucket, leaser: leaser, objectSyncer: objectSyncer, clock: clock, id: id, name: o.Name, attrs: attrs, gcsChunkSize: gcsChunkSize, src: *o, content: mutable.NewContent( gcsproxy.NewReadProxy( o, nil, // Initial read lease gcsChunkSize, leaser, bucket), clock), } f.lc.Init(id) // Set up invariant checking. f.mu = syncutil.NewInvariantMutex(f.checkInvariants) return }