Beispiel #1
0
func TestFileWriteRead(t *testing.T) {
	snapshotio := inodedb.NewSimpleDBStateSnapshotIO()
	txio := inodedb.NewSimpleDBTransactionLogIO()
	idb, err := inodedb.NewEmptyDB(snapshotio, txio)
	if err != nil {
		t.Errorf("NewEmptyDB failed: %v", err)
		return
	}

	bs := tu.TestFileBlobStore()
	fs := otaru.NewFileSystem(idb, bs, tu.TestCipher())
	h, err := fs.OpenFileFullPath("/hello.txt", flags.O_CREATE|flags.O_RDWR, 0666)
	if err != nil {
		t.Errorf("OpenFileFullPath failed: %v", err)
		return
	}

	err = h.PWrite(tu.HelloWorld, 0)
	if err != nil {
		t.Errorf("PWrite failed: %v", err)
	}

	buf := make([]byte, 32)
	n, err := h.ReadAt(buf, 0)
	if err != nil {
		t.Errorf("PRead failed: %v", err)
	}
	buf = buf[:n]
	if n != len(tu.HelloWorld) {
		t.Errorf("n: %d", n)
	}
	if !bytes.Equal(tu.HelloWorld, buf) {
		t.Errorf("PRead content != PWrite content: %v", buf)
	}
}
Beispiel #2
0
func TestCreateFile(t *testing.T) {
	db, err := i.NewEmptyDB(i.NewSimpleDBStateSnapshotIO(), i.NewSimpleDBTransactionLogIO())
	if err != nil {
		t.Errorf("Failed to NewEmptyDB: %v", err)
		return
	}

	nlock, err := db.LockNode(i.AllocateNewNodeID)
	if err != nil {
		t.Errorf("Failed to LockNode: %v", err)
		return
	}

	tx := i.DBTransaction{Ops: []i.DBOperation{
		&i.CreateNodeOp{NodeLock: nlock, OrigPath: "/hoge.txt", Type: i.FileNodeT},
		&i.HardLinkOp{NodeLock: i.NodeLock{1, i.NoTicket}, Name: "hoge.txt", TargetID: nlock.ID},
	}}
	if _, err := db.ApplyTransaction(tx); err != nil {
		t.Errorf("Failed to apply tx: %v", err)
	}

	if err := db.UnlockNode(nlock); err != nil {
		t.Errorf("Failed to UnlockNode: %v", err)
	}

	fbps, errs := db.Fsck()
	if len(fbps) != 0 {
		t.Errorf("Fsck returned used fbp on db: %v", fbps)
	}
	if len(errs) != 0 {
		t.Errorf("Fsck returned err on db: %v", errs)
	}
}
Beispiel #3
0
func TestINodeDB_Rollback(t *testing.T) {
	sio := i.NewSimpleDBStateSnapshotIO()
	txio := i.NewSimpleDBTransactionLogIO()

	db, err := i.NewEmptyDB(sio, txio)
	if err != nil {
		t.Errorf("Failed to NewEmptyDB: %v", err)
		return
	}

	tx := i.DBTransaction{Ops: []i.DBOperation{
		&i.CreateNodeOp{NodeLock: i.NodeLock{2, 123456}, OrigPath: "/hoge.txt", Type: i.FileNodeT},
		&i.HardLinkOp{NodeLock: i.NodeLock{1, i.NoTicket}, Name: "hoge.txt", TargetID: 2},
	}}
	if _, err := db.ApplyTransaction(tx); err != nil {
		t.Errorf("ApplyTransaction failed: %v", err)
		return
	}

	txF := i.DBTransaction{Ops: []i.DBOperation{
		&i.AlwaysFailForTestingOp{},
	}}
	if _, err := db.ApplyTransaction(txF); err == nil {
		t.Errorf("ApplyTransaction succeeded unexpectedly!")
	}
}
Beispiel #4
0
func TestFileWriteRead(t *testing.T) {
	snapshotio := inodedb.NewSimpleDBStateSnapshotIO()
	txio := inodedb.NewSimpleDBTransactionLogIO()
	idb, err := inodedb.NewEmptyDB(snapshotio, txio)
	if err != nil {
		t.Errorf("NewEmptyDB failed: %v", err)
		return
	}

	bs := TestFileBlobStore()
	fs := otaru.NewFileSystem(idb, bs, TestCipher())
	h, err := fs.OpenFileFullPath("/hello.txt", flags.O_CREATE|flags.O_RDWR, 0666)
	if err != nil {
		t.Errorf("OpenFileFullPath failed: %v", err)
		return
	}

	err = h.PWrite(0, []byte("hello world!\n"))
	if err != nil {
		t.Errorf("PWrite failed: %v", err)
	}

	buf := make([]byte, 13)
	err = h.PRead(0, buf)
	if err != nil {
		t.Errorf("PRead failed: %v", err)
	}
	if !bytes.Equal([]byte("hello world!\n"), buf) {
		t.Errorf("PRead content != PWrite content")
	}
}
Beispiel #5
0
func TestNewEmptyDB_ShouldFailOnNonEmptySnapsshotIO(t *testing.T) {
	sio := i.NewSimpleDBStateSnapshotIO()
	{
		db, err := i.NewEmptyDB(sio, i.NewSimpleDBTransactionLogIO())
		if err != nil {
			t.Errorf("Failed to NewEmptyDB: %v", err)
			return
		}
		if err := db.Sync(); err != nil {
			t.Errorf("Failed to Sync DB: %v", err)
			return
		}
	}

	_, err := i.NewEmptyDB(sio, i.NewSimpleDBTransactionLogIO())
	if err == nil {
		t.Errorf("NewEmptyDB should fail on non-empty snapshot io")
		return
	}
}
Beispiel #6
0
func fusetestFileSystem() *otaru.FileSystem {
	sio := inodedb.NewSimpleDBStateSnapshotIO()
	txio := inodedb.NewSimpleDBTransactionLogIO()

	idb, err := inodedb.NewEmptyDB(sio, txio)
	if err != nil {
		log.Fatalf("NewEmptyDB failed: %v", err)
	}

	bs := TestFileBlobStore()
	fs := otaru.NewFileSystem(idb, bs, TestCipher())

	return fs
}
func TestSS_SaveRestore(t *testing.T) {
	loc := datastore.NewINodeDBSSLocator(authtu.TestDSConfig(testRootKey()))
	if _, err := loc.DeleteAll(); err != nil {
		t.Errorf("Failed to loc.DeleteAll: %v", err)
	}

	bs := tu.TestFileBlobStore()
	sio := blobstoredbstatesnapshotio.New(bs, tu.TestCipher(), loc)

	db, err := inodedb.NewEmptyDB(sio, inodedb.NewSimpleDBTransactionLogIO())
	if err != nil {
		t.Errorf("Failed to NewEmptyDB: %v", err)
		return
	}
	if err := db.Sync(); err != nil {
		t.Errorf("Failed to Sync DB: %v", err)
		return
	}

	_, err = inodedb.NewDB(sio, inodedb.NewSimpleDBTransactionLogIO())
	if err != nil {
		t.Errorf("Failed to NewDB: %v", err)
	}
}
Beispiel #8
0
func TestNewEmptyDB_ShouldFailOnNonEmptyTxIO(t *testing.T) {
	sio := i.NewSimpleDBStateSnapshotIO()
	txio := i.NewSimpleDBTransactionLogIO()

	tx := i.DBTransaction{TxID: 123, Ops: []i.DBOperation{
		&i.CreateNodeOp{NodeLock: i.NodeLock{2, 123456}, OrigPath: "/hoge.txt", Type: i.FileNodeT},
		&i.HardLinkOp{NodeLock: i.NodeLock{1, i.NoTicket}, Name: "hoge.txt", TargetID: 2},
	}}
	if err := txio.AppendTransaction(tx); err != nil {
		t.Errorf("AppendTransaction failed: %v", err)
		return
	}

	_, err := i.NewEmptyDB(sio, txio)
	if err == nil {
		t.Errorf("NewEmptyDB should fail on non-empty txio")
		return
	}
}
func TestCachedDBTransactionLogIO_SingleTx(t *testing.T) {
	be := idb.NewSimpleDBTransactionLogIO()
	ctxio := idb.NewCachedDBTransactionLogIO(be)

	if err := ctxio.AppendTransaction(testTx(1)); err != nil {
		t.Errorf("AppendTransaction failed: %v", err)
	}

	txs, err := ctxio.QueryTransactions(1)
	if err != nil {
		t.Errorf("QueryTransactions failed: %v", err)
	}

	txs2, err := be.QueryTransactions(1)
	if err != nil {
		t.Errorf("be.QueryTransactions failed: %v", err)
	}

	if !reflect.DeepEqual(txs, txs2) {
		t.Errorf("mismatch %+v != %+v", txs, txs2)
	}
}
Beispiel #10
0
func TestInitialState(t *testing.T) {
	db, err := i.NewEmptyDB(i.NewSimpleDBStateSnapshotIO(), i.NewSimpleDBTransactionLogIO())
	if err != nil {
		t.Errorf("Failed to NewEmptyDB: %v", err)
		return
	}

	nv, _, err := db.QueryNode(1, false)
	if err != nil {
		t.Errorf("Failed to query root dir")
		return
	}
	if nv.GetType() != i.DirNodeT {
		t.Errorf("root dir not found!")
	}

	fbps, errs := db.Fsck()
	if len(fbps) != 0 {
		t.Errorf("Fsck returned used fbp on new empty db: %v", fbps)
	}
	if len(errs) != 0 {
		t.Errorf("Fsck returned err on new empty db: %v", errs)
	}
}
Beispiel #11
0
func NewOtaru(cfg *Config, oneshotcfg *OneshotConfig) (*Otaru, error) {
	o := &Otaru{}

	var err error

	key := btncrypt.KeyFromPassword(cfg.Password)
	o.C, err = btncrypt.NewCipher(key)
	if err != nil {
		o.Close()
		return nil, fmt.Errorf("Failed to init Cipher: %v", err)
	}

	o.S = scheduler.NewScheduler()

	if !cfg.LocalDebug {
		o.Clisrc, err = auth.GetGCloudClientSource(
			path.Join(os.Getenv("HOME"), ".otaru", "credentials.json"),
			path.Join(os.Getenv("HOME"), ".otaru", "tokencache.json"),
			false)
		if err != nil {
			o.Close()
			return nil, fmt.Errorf("Failed to init GCloudClientSource: %v", err)
		}
	}

	o.CacheTgtBS, err = blobstore.NewFileBlobStore(cfg.CacheDir, oflags.O_RDWRCREATE)
	if err != nil {
		o.Close()
		return nil, fmt.Errorf("Failed to init FileBlobStore: %v", err)
	}

	if !cfg.LocalDebug {
		o.DefaultBS, err = gcs.NewGCSBlobStore(cfg.ProjectName, cfg.BucketName, o.Clisrc, oflags.O_RDWRCREATE)
		if err != nil {
			o.Close()
			return nil, fmt.Errorf("Failed to init GCSBlobStore: %v", err)
		}
		if !cfg.UseSeparateBucketForMetadata {
			o.BackendBS = o.DefaultBS
		} else {
			metabucketname := fmt.Sprintf("%s-meta", cfg.BucketName)
			o.MetadataBS, err = gcs.NewGCSBlobStore(cfg.ProjectName, metabucketname, o.Clisrc, oflags.O_RDWRCREATE)
			if err != nil {
				o.Close()
				return nil, fmt.Errorf("Failed to init GCSBlobStore (metadata): %v", err)
			}

			o.BackendBS = blobstore.Mux{
				blobstore.MuxEntry{metadata.IsMetadataBlobpath, o.MetadataBS},
				blobstore.MuxEntry{nil, o.DefaultBS},
			}
		}
	} else {
		o.BackendBS, err = blobstore.NewFileBlobStore(path.Join(os.Getenv("HOME"), ".otaru", "bbs"), oflags.O_RDWRCREATE)
	}

	queryFn := chunkstore.NewQueryChunkVersion(o.C)
	o.CBS, err = cachedblobstore.New(o.BackendBS, o.CacheTgtBS, oflags.O_RDWRCREATE /* FIXME */, queryFn)
	if err != nil {
		o.Close()
		return nil, fmt.Errorf("Failed to init CachedBlobStore: %v", err)
	}
	o.CSS = cachedblobstore.NewCacheSyncScheduler(o.CBS)

	o.SIO = otaru.NewBlobStoreDBStateSnapshotIO(o.CBS, o.C)

	if !cfg.LocalDebug {
		o.TxIO, err = datastore.NewDBTransactionLogIO(cfg.ProjectName, cfg.BucketName, o.C, o.Clisrc)
	} else {
		o.TxIO = inodedb.NewSimpleDBTransactionLogIO()
		err = nil
	}
	if err != nil {
		o.Close()
		return nil, fmt.Errorf("Failed to init gcloud DBTransactionLogIO: %v", err)
	}

	if oneshotcfg.Mkfs {
		o.IDBBE, err = inodedb.NewEmptyDB(o.SIO, o.TxIO)
		if err != nil {
			o.Close()
			return nil, fmt.Errorf("NewEmptyDB failed: %v", err)
		}
	} else {
		o.IDBBE, err = inodedb.NewDB(o.SIO, o.TxIO)
		if err != nil {
			o.Close()
			return nil, fmt.Errorf("NewDB failed: %v", err)
		}
	}

	o.IDBS = inodedb.NewDBService(o.IDBBE)
	o.IDBSS = util.NewSyncScheduler(o.IDBS, 30*time.Second)

	o.FS = otaru.NewFileSystem(o.IDBS, o.CBS, o.C)
	o.MGMT = mgmt.NewServer()
	o.setupMgmtAPIs()
	if err := o.runMgmtServer(); err != nil {
		o.Close()
		return nil, fmt.Errorf("Mgmt server run failed: %v", err)
	}

	return o, nil
}
func TestSS_AutoAvoidCorruptedSnapshot(t *testing.T) {
	loc := datastore.NewINodeDBSSLocator(authtu.TestDSConfig(testRootKey()))
	if _, err := loc.DeleteAll(); err != nil {
		t.Errorf("Failed to loc.DeleteAll: %v", err)
	}

	bs := tu.TestFileBlobStore()
	sio := blobstoredbstatesnapshotio.New(bs, tu.TestCipher(), loc)
	txlogio := inodedb.NewSimpleDBTransactionLogIO()

	{
		db, err := inodedb.NewEmptyDB(sio, txlogio)
		if err != nil {
			t.Errorf("Failed to NewEmptyDB: %v", err)
			return
		}

		// create 1st snapshot
		if err := db.Sync(); err != nil {
			t.Errorf("Failed to Sync DB: %v", err)
			return
		}

		// apply some mod to inodedb
		nlock, err := db.LockNode(inodedb.AllocateNewNodeID)
		if err != nil {
			t.Errorf("Failed to LockNode: %v", err)
			return
		}

		tx := inodedb.DBTransaction{Ops: []inodedb.DBOperation{
			&inodedb.CreateNodeOp{NodeLock: nlock, OrigPath: "/hoge.txt", Type: inodedb.FileNodeT},
			&inodedb.HardLinkOp{NodeLock: inodedb.NodeLock{1, inodedb.NoTicket}, Name: "hoge.txt", TargetID: nlock.ID},
		}}
		if _, err := db.ApplyTransaction(tx); err != nil {
			t.Errorf("Failed to apply tx: %v", err)
			return
		}

		if err := db.UnlockNode(nlock); err != nil {
			t.Errorf("Failed to UnlockNode: %v", err)
			return
		}

		// create 2nd snapshot
		if err := db.Sync(); err != nil {
			t.Errorf("Failed to Sync DB (2): %v", err)
			return
		}
	}

	if _, err := inodedb.NewDB(sio, txlogio); err != nil {
		t.Errorf("Failed to NewDB (uncorrupted): %v", err)
		return
	}

	// destroy latest snapshot (corrupt data)
	ssbp, err := loc.Locate(0)
	if err != nil {
		t.Errorf("Failed to locate latest ssbp: %v", err)
		return
	}
	{
		wc, err := bs.OpenWriter(ssbp)
		if err != nil {
			t.Errorf("Failed to OpenWriter: %v", err)
			return
		}
		if _, err := wc.Write([]byte("hoge")); err != nil {
			t.Errorf("Failed to Write: %v", err)
		}
		wc.Close()
	}

	{
		_, err = inodedb.NewDB(sio, txlogio)
		if err != nil {
			t.Errorf("Failed to NewDB (corrupted): %v", err)
			return
		}
	}

	// destroy latest snapshot (remove ss blob)
	if err := bs.RemoveBlob(ssbp); err != nil {
		t.Errorf("Failed to RemoveBlob: %v", err)
	}

	{
		_, err = inodedb.NewDB(sio, txlogio)
		if err != nil {
			t.Errorf("Failed to NewDB (ss blob removed): %v", err)
			return
		}
	}
}
Beispiel #13
0
func NewOtaru(cfg *Config, oneshotcfg *OneshotConfig) (*Otaru, error) {
	o := &Otaru{}

	var err error

	key := btncrypt.KeyFromPassword(cfg.Password)
	o.C, err = btncrypt.NewCipher(key)
	if err != nil {
		o.Close()
		return nil, fmt.Errorf("Failed to init Cipher: %v", err)
	}

	o.S = scheduler.NewScheduler()

	if !cfg.LocalDebug {
		o.Tsrc, err = auth.GetGCloudTokenSource(context.TODO(), cfg.CredentialsFilePath, cfg.TokenCacheFilePath, false)
		if err != nil {
			o.Close()
			return nil, fmt.Errorf("Failed to init GCloudClientSource: %v", err)
		}
		o.DSCfg = datastore.NewConfig(cfg.ProjectName, cfg.BucketName, o.C, o.Tsrc)
		o.GL = datastore.NewGlobalLocker(o.DSCfg, GenHostName(), "FIXME: fill info")
		if err := o.GL.Lock(); err != nil {
			return nil, err
		}
	}

	o.CacheTgtBS, err = blobstore.NewFileBlobStore(cfg.CacheDir, oflags.O_RDWRCREATE)
	if err != nil {
		o.Close()
		return nil, fmt.Errorf("Failed to init FileBlobStore: %v", err)
	}

	if !cfg.LocalDebug {
		o.DefaultBS, err = gcs.NewGCSBlobStore(cfg.ProjectName, cfg.BucketName, o.Tsrc, oflags.O_RDWRCREATE)
		if err != nil {
			o.Close()
			return nil, fmt.Errorf("Failed to init GCSBlobStore: %v", err)
		}
		if !cfg.UseSeparateBucketForMetadata {
			o.BackendBS = o.DefaultBS
		} else {
			metabucketname := fmt.Sprintf("%s-meta", cfg.BucketName)
			o.MetadataBS, err = gcs.NewGCSBlobStore(cfg.ProjectName, metabucketname, o.Tsrc, oflags.O_RDWRCREATE)
			if err != nil {
				o.Close()
				return nil, fmt.Errorf("Failed to init GCSBlobStore (metadata): %v", err)
			}

			o.BackendBS = blobstore.Mux{
				blobstore.MuxEntry{metadata.IsMetadataBlobpath, o.MetadataBS},
				blobstore.MuxEntry{nil, o.DefaultBS},
			}
		}
	} else {
		o.BackendBS, err = blobstore.NewFileBlobStore(path.Join(os.Getenv("HOME"), ".otaru", "bbs"), oflags.O_RDWRCREATE)
	}

	queryFn := chunkstore.NewQueryChunkVersion(o.C)
	o.CBS, err = cachedblobstore.New(o.BackendBS, o.CacheTgtBS, o.S, oflags.O_RDWRCREATE /* FIXME */, queryFn)
	if err != nil {
		o.Close()
		return nil, fmt.Errorf("Failed to init CachedBlobStore: %v", err)
	}
	if err := o.CBS.RestoreState(o.C); err != nil {
		logger.Warningf(mylog, "Attempted to restore cachedblobstore state but failed: %v", err)
	}
	o.CSS = cachedblobstore.NewCacheSyncScheduler(o.CBS)

	if !cfg.LocalDebug {
		o.SSLoc = datastore.NewINodeDBSSLocator(o.DSCfg)
	} else {
		logger.Panicf(mylog, "Implement mock sslocator that doesn't depend on gcloud/datastore")
	}
	o.SIO = blobstoredbstatesnapshotio.New(o.CBS, o.C, o.SSLoc)

	if !cfg.LocalDebug {
		txio := datastore.NewDBTransactionLogIO(o.DSCfg)
		o.TxIO = txio
		o.TxIOSS = util.NewSyncScheduler(txio, 300*time.Millisecond)
	} else {
		o.TxIO = inodedb.NewSimpleDBTransactionLogIO()
	}
	o.CTxIO = inodedb.NewCachedDBTransactionLogIO(o.TxIO)

	if oneshotcfg.Mkfs {
		o.IDBBE, err = inodedb.NewEmptyDB(o.SIO, o.CTxIO)
		if err != nil {
			o.Close()
			return nil, fmt.Errorf("NewEmptyDB failed: %v", err)
		}
	} else {
		o.IDBBE, err = inodedb.NewDB(o.SIO, o.CTxIO)
		if err != nil {
			o.Close()
			return nil, fmt.Errorf("NewDB failed: %v", err)
		}
	}

	o.IDBS = inodedb.NewDBService(o.IDBBE)
	o.IDBSS = util.NewSyncScheduler(o.IDBS, 30*time.Second)

	o.FS = otaru.NewFileSystem(o.IDBS, o.CBS, o.C)
	o.MGMT = mgmt.NewServer()
	if err := o.runMgmtServer(); err != nil {
		o.Close()
		return nil, fmt.Errorf("Mgmt server run failed: %v", err)
	}

	return o, nil
}