You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
4.5 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
6 years ago
6 years ago
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
5 years ago
7 years ago
7 years ago
7 years ago
5 years ago
7 years ago
5 years ago
7 years ago
7 years ago
4 years ago
5 years ago
7 years ago
5 years ago
7 years ago
  1. package cassandra
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/gocql/gocql"
  6. "github.com/chrislusf/seaweedfs/weed/filer2"
  7. "github.com/chrislusf/seaweedfs/weed/glog"
  8. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  9. "github.com/chrislusf/seaweedfs/weed/util"
  10. )
  11. func init() {
  12. filer2.Stores = append(filer2.Stores, &CassandraStore{})
  13. }
  14. type CassandraStore struct {
  15. cluster *gocql.ClusterConfig
  16. session *gocql.Session
  17. }
  18. func (store *CassandraStore) GetName() string {
  19. return "cassandra"
  20. }
  21. func (store *CassandraStore) Initialize(configuration util.Configuration, prefix string) (err error) {
  22. return store.initialize(
  23. configuration.GetString(prefix+"keyspace"),
  24. configuration.GetStringSlice(prefix+"hosts"),
  25. )
  26. }
  27. func (store *CassandraStore) initialize(keyspace string, hosts []string) (err error) {
  28. store.cluster = gocql.NewCluster(hosts...)
  29. store.cluster.Keyspace = keyspace
  30. store.cluster.Consistency = gocql.LocalQuorum
  31. store.session, err = store.cluster.CreateSession()
  32. if err != nil {
  33. glog.V(0).Infof("Failed to open cassandra store, hosts %v, keyspace %s", hosts, keyspace)
  34. }
  35. return
  36. }
  37. func (store *CassandraStore) BeginTransaction(ctx context.Context) (context.Context, error) {
  38. return ctx, nil
  39. }
  40. func (store *CassandraStore) CommitTransaction(ctx context.Context) error {
  41. return nil
  42. }
  43. func (store *CassandraStore) RollbackTransaction(ctx context.Context) error {
  44. return nil
  45. }
  46. func (store *CassandraStore) InsertEntry(ctx context.Context, entry *filer2.Entry) (err error) {
  47. dir, name := entry.FullPath.DirAndName()
  48. meta, err := entry.EncodeAttributesAndChunks()
  49. if err != nil {
  50. return fmt.Errorf("encode %s: %s", entry.FullPath, err)
  51. }
  52. if err := store.session.Query(
  53. "INSERT INTO filemeta (directory,name,meta) VALUES(?,?,?) USING TTL ? ",
  54. dir, name, meta, entry.TtlSec).Exec(); err != nil {
  55. return fmt.Errorf("insert %s: %s", entry.FullPath, err)
  56. }
  57. return nil
  58. }
  59. func (store *CassandraStore) UpdateEntry(ctx context.Context, entry *filer2.Entry) (err error) {
  60. return store.InsertEntry(ctx, entry)
  61. }
  62. func (store *CassandraStore) FindEntry(ctx context.Context, fullpath util.FullPath) (entry *filer2.Entry, err error) {
  63. dir, name := fullpath.DirAndName()
  64. var data []byte
  65. if err := store.session.Query(
  66. "SELECT meta FROM filemeta WHERE directory=? AND name=?",
  67. dir, name).Consistency(gocql.One).Scan(&data); err != nil {
  68. if err != gocql.ErrNotFound {
  69. return nil, filer_pb.ErrNotFound
  70. }
  71. }
  72. if len(data) == 0 {
  73. return nil, filer_pb.ErrNotFound
  74. }
  75. entry = &filer2.Entry{
  76. FullPath: fullpath,
  77. }
  78. err = entry.DecodeAttributesAndChunks(data)
  79. if err != nil {
  80. return entry, fmt.Errorf("decode %s : %v", entry.FullPath, err)
  81. }
  82. return entry, nil
  83. }
  84. func (store *CassandraStore) DeleteEntry(ctx context.Context, fullpath util.FullPath) error {
  85. dir, name := fullpath.DirAndName()
  86. if err := store.session.Query(
  87. "DELETE FROM filemeta WHERE directory=? AND name=?",
  88. dir, name).Exec(); err != nil {
  89. return fmt.Errorf("delete %s : %v", fullpath, err)
  90. }
  91. return nil
  92. }
  93. func (store *CassandraStore) DeleteFolderChildren(ctx context.Context, fullpath util.FullPath) error {
  94. if err := store.session.Query(
  95. "DELETE FROM filemeta WHERE directory=?",
  96. fullpath).Exec(); err != nil {
  97. return fmt.Errorf("delete %s : %v", fullpath, err)
  98. }
  99. return nil
  100. }
  101. func (store *CassandraStore) ListDirectoryPrefixedEntries(ctx context.Context, fullpath util.FullPath, startFileName string, inclusive bool, limit int, prefix string) (entries []*filer2.Entry, err error) {
  102. return nil, filer2.ErrUnsupportedListDirectoryPrefixed
  103. }
  104. func (store *CassandraStore) ListDirectoryEntries(ctx context.Context, fullpath util.FullPath, startFileName string, inclusive bool,
  105. limit int) (entries []*filer2.Entry, err error) {
  106. cqlStr := "SELECT NAME, meta FROM filemeta WHERE directory=? AND name>? ORDER BY NAME ASC LIMIT ?"
  107. if inclusive {
  108. cqlStr = "SELECT NAME, meta FROM filemeta WHERE directory=? AND name>=? ORDER BY NAME ASC LIMIT ?"
  109. }
  110. var data []byte
  111. var name string
  112. iter := store.session.Query(cqlStr, string(fullpath), startFileName, limit).Iter()
  113. for iter.Scan(&name, &data) {
  114. entry := &filer2.Entry{
  115. FullPath: util.NewFullPath(string(fullpath), name),
  116. }
  117. if decodeErr := entry.DecodeAttributesAndChunks(data); decodeErr != nil {
  118. err = decodeErr
  119. glog.V(0).Infof("list %s : %v", entry.FullPath, err)
  120. break
  121. }
  122. entries = append(entries, entry)
  123. }
  124. if err := iter.Close(); err != nil {
  125. glog.V(0).Infof("list iterator close: %v", err)
  126. }
  127. return entries, err
  128. }
  129. func (store *CassandraStore) Shutdown() {
  130. store.session.Close()
  131. }