Konstantin Lebedev
4 years ago
7 changed files with 195 additions and 0 deletions
-
3docker/Makefile
-
59docker/local-replicate-compose.yml
-
16docker/notification.toml
-
11docker/replication.toml
-
1weed/command/filer_replication.go
-
4weed/command/scaffold.go
-
101weed/replication/sink/localsink/local_sink.go
@ -0,0 +1,59 @@ |
|||
version: '2' |
|||
|
|||
services: |
|||
master: |
|||
image: chrislusf/seaweedfs:local |
|||
ports: |
|||
- 9333:9333 |
|||
- 19333:19333 |
|||
command: "master -ip=master" |
|||
volume: |
|||
image: chrislusf/seaweedfs:local |
|||
ports: |
|||
- 8080:8080 |
|||
- 18080:18080 |
|||
command: "volume -mserver=master:9333 -port=8080 -ip=volume -preStopSeconds=1" |
|||
depends_on: |
|||
- master |
|||
filer: |
|||
image: chrislusf/seaweedfs:local |
|||
ports: |
|||
- 8888:8888 |
|||
- 18888:18888 |
|||
command: '-v=9 filer -master="master:9333"' |
|||
restart: on-failure |
|||
volumes: |
|||
- ./notification.toml:/etc/seaweedfs/notification.toml |
|||
depends_on: |
|||
- master |
|||
- volume |
|||
- rabbitmq |
|||
- replicate |
|||
environment: |
|||
RABBIT_SERVER_URL: "amqp://guest:guest@rabbitmq:5672/" |
|||
replicate: |
|||
image: chrislusf/seaweedfs:local |
|||
command: '-v=9 filer.replicate' |
|||
restart: on-failure |
|||
volumes: |
|||
- ./notification.toml:/etc/seaweedfs/notification.toml |
|||
- ./replication.toml:/etc/seaweedfs/replication.toml |
|||
depends_on: |
|||
- rabbitmq |
|||
environment: |
|||
RABBIT_SERVER_URL: "amqp://guest:guest@rabbitmq:5672/" |
|||
s3: |
|||
image: chrislusf/seaweedfs:local |
|||
ports: |
|||
- 8333:8333 |
|||
command: 's3 -filer="filer:8888"' |
|||
depends_on: |
|||
- master |
|||
- volume |
|||
- filer |
|||
rabbitmq: |
|||
image: rabbitmq:3.8.10-management-alpine |
|||
ports: |
|||
- 5672:5672 |
|||
- 15671:15671 |
|||
- 15672:15672 |
@ -0,0 +1,16 @@ |
|||
[notification.log] |
|||
# this is only for debugging perpose and does not work with "weed filer.replicate" |
|||
enabled = false |
|||
|
|||
|
|||
[notification.gocdk_pub_sub] |
|||
# The Go Cloud Development Kit (https://gocloud.dev). |
|||
# PubSub API (https://godoc.org/gocloud.dev/pubsub). |
|||
# Supports AWS SNS/SQS, Azure Service Bus, Google PubSub, NATS and RabbitMQ. |
|||
enabled = true |
|||
# This URL will Dial the RabbitMQ server at the URL in the environment |
|||
# variable RABBIT_SERVER_URL and open the exchange "myexchange". |
|||
# The exchange must have already been created by some other means, like |
|||
# the RabbitMQ management plugin. |
|||
topic_url = "rabbit://swexchange" |
|||
sub_url = "rabbit://swqueue" |
@ -0,0 +1,11 @@ |
|||
[source.filer] |
|||
enabled = true |
|||
grpcAddress = "filer:18888" |
|||
# all files under this directory tree are replicated. |
|||
# this is not a directory on your hard drive, but on your filer. |
|||
# i.e., all files with this "prefix" are sent to notification message queue. |
|||
directory = "/buckets" |
|||
|
|||
[sink.local] |
|||
enabled = true |
|||
directory = "/data" |
@ -0,0 +1,101 @@ |
|||
package localsink |
|||
|
|||
import ( |
|||
"github.com/chrislusf/seaweedfs/weed/filer" |
|||
"github.com/chrislusf/seaweedfs/weed/glog" |
|||
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb" |
|||
"github.com/chrislusf/seaweedfs/weed/replication/repl_util" |
|||
"github.com/chrislusf/seaweedfs/weed/replication/sink" |
|||
"github.com/chrislusf/seaweedfs/weed/replication/source" |
|||
"github.com/chrislusf/seaweedfs/weed/util" |
|||
"io/ioutil" |
|||
"os" |
|||
"path/filepath" |
|||
"strings" |
|||
) |
|||
|
|||
type LocalSink struct { |
|||
dir string |
|||
filerSource *source.FilerSource |
|||
} |
|||
|
|||
func init() { |
|||
sink.Sinks = append(sink.Sinks, &LocalSink{}) |
|||
} |
|||
|
|||
func (localsink *LocalSink) SetSourceFiler(s *source.FilerSource) { |
|||
localsink.filerSource = s |
|||
} |
|||
|
|||
func (localsink *LocalSink) GetName() string { |
|||
return "local" |
|||
} |
|||
|
|||
func (localsink *LocalSink) isMultiPartEntry(key string) bool { |
|||
return strings.HasSuffix(key, ".part") && strings.Contains(key, "/.uploads/") |
|||
} |
|||
|
|||
func (localsink *LocalSink) initialize(dir string) error { |
|||
localsink.dir = dir |
|||
return nil |
|||
} |
|||
|
|||
func (localsink *LocalSink) Initialize(configuration util.Configuration, prefix string) error { |
|||
dir := configuration.GetString(prefix + "directory") |
|||
glog.V(4).Infof("sink.local.directory: %v", dir) |
|||
return localsink.initialize(dir) |
|||
} |
|||
|
|||
func (localsink *LocalSink) GetSinkToDirectory() string { |
|||
return localsink.dir |
|||
} |
|||
|
|||
func (localsink *LocalSink) DeleteEntry(key string, isDirectory, deleteIncludeChunks bool, signatures []int32) error { |
|||
if localsink.isMultiPartEntry(key) { |
|||
return nil |
|||
} |
|||
glog.V(4).Infof("Delete Entry key: %s", key) |
|||
if err := os.Remove(key); err != nil { |
|||
return err |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (localsink *LocalSink) CreateEntry(key string, entry *filer_pb.Entry, signatures []int32) error { |
|||
if entry.IsDirectory || localsink.isMultiPartEntry(key) { |
|||
return nil |
|||
} |
|||
glog.V(4).Infof("Create Entry key: %s", key) |
|||
|
|||
totalSize := filer.FileSize(entry) |
|||
chunkViews := filer.ViewFromChunks(localsink.filerSource.LookupFileId, entry.Chunks, 0, int64(totalSize)) |
|||
|
|||
dir := filepath.Dir(key) |
|||
|
|||
if _, err := os.Stat(dir); os.IsNotExist(err) { |
|||
glog.V(4).Infof("Create Direcotry key: %s", dir) |
|||
if err = os.MkdirAll(dir, 0); err != nil { |
|||
return err |
|||
} |
|||
} |
|||
|
|||
writeFunc := func(data []byte) error { |
|||
writeErr := ioutil.WriteFile(key, data, 0) |
|||
return writeErr |
|||
} |
|||
|
|||
if err := repl_util.CopyFromChunkViews(chunkViews, localsink.filerSource, writeFunc); err != nil { |
|||
return err |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func (localsink *LocalSink) UpdateEntry(key string, oldEntry *filer_pb.Entry, newParentPath string, newEntry *filer_pb.Entry, deleteIncludeChunks bool, signatures []int32) (foundExistingEntry bool, err error) { |
|||
if localsink.isMultiPartEntry(key) { |
|||
return true, nil |
|||
} |
|||
glog.V(4).Infof("Update Entry key: %s", key) |
|||
// do delete and create
|
|||
return false, nil |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue