2015-01-06 07:03:27 +00:00
|
|
|
package cassandra_store
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2016-11-28 07:01:04 +00:00
|
|
|
"strings"
|
2016-11-29 04:07:27 +00:00
|
|
|
|
2016-09-08 03:35:54 +00:00
|
|
|
"github.com/chrislusf/seaweedfs/weed/filer"
|
2016-06-03 01:09:14 +00:00
|
|
|
"github.com/chrislusf/seaweedfs/weed/glog"
|
2015-01-06 07:03:27 +00:00
|
|
|
|
|
|
|
"github.com/gocql/gocql"
|
|
|
|
)
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Basically you need a table just like this:
|
|
|
|
|
|
|
|
CREATE TABLE seaweed_files (
|
|
|
|
path varchar,
|
|
|
|
fids list<varchar>,
|
|
|
|
PRIMARY KEY (path)
|
|
|
|
);
|
|
|
|
|
|
|
|
Need to match flat_namespace.FlatNamespaceStore interface
|
|
|
|
Put(fullFileName string, fid string) (err error)
|
|
|
|
Get(fullFileName string) (fid string, err error)
|
|
|
|
Delete(fullFileName string) (fid string, err error)
|
|
|
|
|
|
|
|
*/
|
|
|
|
type CassandraStore struct {
|
|
|
|
cluster *gocql.ClusterConfig
|
|
|
|
session *gocql.Session
|
|
|
|
}
|
|
|
|
|
2016-11-28 08:03:39 +00:00
|
|
|
func NewCassandraStore(keyspace string, hosts string) (c *CassandraStore, err error) {
|
2015-01-06 07:03:27 +00:00
|
|
|
c = &CassandraStore{}
|
2016-11-29 04:07:27 +00:00
|
|
|
s := strings.Split(hosts, ",")
|
|
|
|
if len(s) == 1 {
|
|
|
|
glog.V(2).Info("Only one cassandra node to connect! A cluster is Recommended! Now using:", string(hosts))
|
|
|
|
c.cluster = gocql.NewCluster(hosts)
|
|
|
|
} else if len(s) > 1 {
|
|
|
|
c.cluster = gocql.NewCluster(s...)
|
|
|
|
}
|
2015-01-06 07:03:27 +00:00
|
|
|
c.cluster.Keyspace = keyspace
|
|
|
|
c.cluster.Consistency = gocql.Quorum
|
|
|
|
c.session, err = c.cluster.CreateSession()
|
|
|
|
if err != nil {
|
|
|
|
glog.V(0).Infof("Failed to open cassandra store, hosts %v, keyspace %s", hosts, keyspace)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CassandraStore) Put(fullFileName string, fid string) (err error) {
|
|
|
|
var input []string
|
|
|
|
input = append(input, fid)
|
|
|
|
if err := c.session.Query(
|
|
|
|
`INSERT INTO seaweed_files (path, fids) VALUES (?, ?)`,
|
|
|
|
fullFileName, input).Exec(); err != nil {
|
|
|
|
glog.V(0).Infof("Failed to save file %s with id %s: %v", fullFileName, fid, err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
func (c *CassandraStore) Get(fullFileName string) (fid string, err error) {
|
|
|
|
var output []string
|
|
|
|
if err := c.session.Query(
|
|
|
|
`select fids FROM seaweed_files WHERE path = ? LIMIT 1`,
|
|
|
|
fullFileName).Consistency(gocql.One).Scan(&output); err != nil {
|
|
|
|
if err != gocql.ErrNotFound {
|
|
|
|
glog.V(0).Infof("Failed to find file %s: %v", fullFileName, fid, err)
|
2016-09-08 03:35:54 +00:00
|
|
|
return "", filer.ErrNotFound
|
2015-01-06 07:03:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(output) == 0 {
|
|
|
|
return "", fmt.Errorf("No file id found for %s", fullFileName)
|
|
|
|
}
|
|
|
|
return output[0], nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Currently the fid is not returned
|
2016-06-10 17:16:19 +00:00
|
|
|
func (c *CassandraStore) Delete(fullFileName string) (err error) {
|
2015-01-06 07:03:27 +00:00
|
|
|
if err := c.session.Query(
|
|
|
|
`DELETE FROM seaweed_files WHERE path = ?`,
|
|
|
|
fullFileName).Exec(); err != nil {
|
|
|
|
if err != gocql.ErrNotFound {
|
|
|
|
glog.V(0).Infof("Failed to delete file %s: %v", fullFileName, err)
|
|
|
|
}
|
2016-06-10 17:16:19 +00:00
|
|
|
return err
|
2015-01-06 07:03:27 +00:00
|
|
|
}
|
2016-06-10 17:16:19 +00:00
|
|
|
return nil
|
2015-01-06 07:03:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CassandraStore) Close() {
|
|
|
|
if c.session != nil {
|
|
|
|
c.session.Close()
|
|
|
|
}
|
|
|
|
}
|