Browse Source
Merge pull request #702 from chrislusf/add_topo_listener
Merge pull request #702 from chrislusf/add_topo_listener
Add volume id location change listenerpull/719/head
Chris Lu
7 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 535 additions and 151 deletions
-
36weed/filer2/filer.go
-
60weed/filer2/filer_master.go
-
8weed/operation/delete_content.go
-
167weed/pb/master_pb/seaweed.pb.go
-
13weed/pb/seaweed.proto
-
20weed/server/filer_grpc_server.go
-
5weed/server/filer_server_handlers_read.go
-
6weed/server/filer_server_handlers_write.go
-
108weed/server/master_grpc_server.go
-
6weed/server/master_server.go
-
11weed/topology/data_node.go
-
5weed/topology/topology.go
-
23weed/topology/topology_map.go
-
1weed/util/http_util.go
-
95weed/wdclient/masterclient.go
-
99weed/wdclient/vid_map.go
-
15weed/wdclient/wdclient.go
@ -1,60 +0,0 @@ |
|||||
package filer2 |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"fmt" |
|
||||
"time" |
|
||||
|
|
||||
"github.com/chrislusf/seaweedfs/weed/glog" |
|
||||
"github.com/chrislusf/seaweedfs/weed/pb/master_pb" |
|
||||
"github.com/chrislusf/seaweedfs/weed/util" |
|
||||
) |
|
||||
|
|
||||
func (fs *Filer) GetMaster() string { |
|
||||
return fs.currentMaster |
|
||||
} |
|
||||
|
|
||||
func (fs *Filer) KeepConnectedToMaster() { |
|
||||
glog.V(0).Infof("Filer bootstraps with masters %v", fs.masters) |
|
||||
for _, master := range fs.masters { |
|
||||
glog.V(0).Infof("Connecting to %v", master) |
|
||||
withMasterClient(master, func(client master_pb.SeaweedClient) error { |
|
||||
stream, err := client.KeepConnected(context.Background()) |
|
||||
if err != nil { |
|
||||
glog.V(0).Infof("failed to keep connected to %s: %v", master, err) |
|
||||
return err |
|
||||
} |
|
||||
|
|
||||
glog.V(0).Infof("Connected to %v", master) |
|
||||
fs.currentMaster = master |
|
||||
|
|
||||
for { |
|
||||
time.Sleep(time.Duration(float32(10*1e3)*0.25) * time.Millisecond) |
|
||||
|
|
||||
if err = stream.Send(&master_pb.Empty{}); err != nil { |
|
||||
glog.V(0).Infof("failed to send to %s: %v", master, err) |
|
||||
return err |
|
||||
} |
|
||||
|
|
||||
if _, err = stream.Recv(); err != nil { |
|
||||
glog.V(0).Infof("failed to receive from %s: %v", master, err) |
|
||||
return err |
|
||||
} |
|
||||
} |
|
||||
}) |
|
||||
fs.currentMaster = "" |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
func withMasterClient(master string, fn func(client master_pb.SeaweedClient) error) error { |
|
||||
|
|
||||
grpcConnection, err := util.GrpcDial(master) |
|
||||
if err != nil { |
|
||||
return fmt.Errorf("fail to dial %s: %v", master, err) |
|
||||
} |
|
||||
defer grpcConnection.Close() |
|
||||
|
|
||||
client := master_pb.NewSeaweedClient(grpcConnection) |
|
||||
|
|
||||
return fn(client) |
|
||||
} |
|
@ -0,0 +1,95 @@ |
|||||
|
package wdclient |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"fmt" |
||||
|
"time" |
||||
|
|
||||
|
"github.com/chrislusf/seaweedfs/weed/glog" |
||||
|
"github.com/chrislusf/seaweedfs/weed/pb/master_pb" |
||||
|
"github.com/chrislusf/seaweedfs/weed/util" |
||||
|
) |
||||
|
|
||||
|
type MasterClient struct { |
||||
|
ctx context.Context |
||||
|
name string |
||||
|
currentMaster string |
||||
|
masters []string |
||||
|
|
||||
|
vidMap |
||||
|
} |
||||
|
|
||||
|
func NewMasterClient(ctx context.Context, clientName string, masters []string) *MasterClient { |
||||
|
return &MasterClient{ |
||||
|
ctx: ctx, |
||||
|
name: clientName, |
||||
|
masters: masters, |
||||
|
vidMap: newVidMap(), |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (mc *MasterClient) GetMaster() string { |
||||
|
return mc.currentMaster |
||||
|
} |
||||
|
|
||||
|
func (mc *MasterClient) KeepConnectedToMaster() { |
||||
|
glog.V(0).Infof("%s bootstraps with masters %v", mc.name, mc.masters) |
||||
|
for { |
||||
|
mc.tryAllMasters() |
||||
|
time.Sleep(time.Second) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (mc *MasterClient) tryAllMasters() { |
||||
|
for _, master := range mc.masters { |
||||
|
glog.V(0).Infof("Connecting to %v", master) |
||||
|
withMasterClient(master, func(client master_pb.SeaweedClient) error { |
||||
|
stream, err := client.KeepConnected(context.Background()) |
||||
|
if err != nil { |
||||
|
glog.V(0).Infof("failed to keep connected to %s: %v", master, err) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
glog.V(0).Infof("Connected to %v", master) |
||||
|
mc.currentMaster = master |
||||
|
|
||||
|
if err = stream.Send(&master_pb.ClientListenRequest{Name: mc.name}); err != nil { |
||||
|
glog.V(0).Infof("failed to send to %s: %v", master, err) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
for { |
||||
|
if volumeLocation, err := stream.Recv(); err != nil { |
||||
|
glog.V(0).Infof("failed to receive from %s: %v", master, err) |
||||
|
return err |
||||
|
} else { |
||||
|
glog.V(0).Infof("volume location: %+v", volumeLocation) |
||||
|
loc := Location{ |
||||
|
Url: volumeLocation.Url, |
||||
|
PublicUrl: volumeLocation.PublicUrl, |
||||
|
} |
||||
|
for _, newVid := range volumeLocation.NewVids { |
||||
|
mc.addLocation(newVid, loc) |
||||
|
} |
||||
|
for _, deletedVid := range volumeLocation.DeletedVids { |
||||
|
mc.deleteLocation(deletedVid, loc) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
mc.currentMaster = "" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func withMasterClient(master string, fn func(client master_pb.SeaweedClient) error) error { |
||||
|
|
||||
|
grpcConnection, err := util.GrpcDial(master) |
||||
|
if err != nil { |
||||
|
return fmt.Errorf("fail to dial %s: %v", master, err) |
||||
|
} |
||||
|
defer grpcConnection.Close() |
||||
|
|
||||
|
client := master_pb.NewSeaweedClient(grpcConnection) |
||||
|
|
||||
|
return fn(client) |
||||
|
} |
@ -0,0 +1,99 @@ |
|||||
|
package wdclient |
||||
|
|
||||
|
import ( |
||||
|
"errors" |
||||
|
"fmt" |
||||
|
"math/rand" |
||||
|
"strconv" |
||||
|
"strings" |
||||
|
"sync" |
||||
|
|
||||
|
"github.com/chrislusf/seaweedfs/weed/glog" |
||||
|
) |
||||
|
|
||||
|
type Location struct { |
||||
|
Url string `json:"url,omitempty"` |
||||
|
PublicUrl string `json:"publicUrl,omitempty"` |
||||
|
} |
||||
|
|
||||
|
type vidMap struct { |
||||
|
sync.RWMutex |
||||
|
vid2Locations map[uint32][]Location |
||||
|
} |
||||
|
|
||||
|
func newVidMap() vidMap { |
||||
|
return vidMap{ |
||||
|
vid2Locations: make(map[uint32][]Location), |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (vc *vidMap) LookupVolumeServerUrl(vid string) (serverUrl string, err error) { |
||||
|
id, err := strconv.Atoi(vid) |
||||
|
if err != nil { |
||||
|
glog.V(1).Infof("Unknown volume id %s", vid) |
||||
|
return "", err |
||||
|
} |
||||
|
|
||||
|
locations := vc.GetLocations(uint32(id)) |
||||
|
if len(locations) == 0 { |
||||
|
return "", fmt.Errorf("volume %d not found", id) |
||||
|
} |
||||
|
|
||||
|
return locations[rand.Intn(len(locations))].Url, nil |
||||
|
} |
||||
|
|
||||
|
func (vc *vidMap) LookupFileId(fileId string) (fullUrl string, err error) { |
||||
|
parts := strings.Split(fileId, ",") |
||||
|
if len(parts) != 2 { |
||||
|
return "", errors.New("Invalid fileId " + fileId) |
||||
|
} |
||||
|
serverUrl, lookupError := vc.LookupVolumeServerUrl(parts[0]) |
||||
|
if lookupError != nil { |
||||
|
return "", lookupError |
||||
|
} |
||||
|
return "http://" + serverUrl + "/" + fileId, nil |
||||
|
} |
||||
|
|
||||
|
func (vc *vidMap) GetLocations(vid uint32) (locations []Location) { |
||||
|
vc.RLock() |
||||
|
defer vc.RUnlock() |
||||
|
|
||||
|
return vc.vid2Locations[vid] |
||||
|
} |
||||
|
|
||||
|
func (vc *vidMap) addLocation(vid uint32, location Location) { |
||||
|
vc.Lock() |
||||
|
defer vc.Unlock() |
||||
|
|
||||
|
locations, found := vc.vid2Locations[vid] |
||||
|
if !found { |
||||
|
vc.vid2Locations[vid] = []Location{location} |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
for _, loc := range locations { |
||||
|
if loc.Url == location.Url { |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
vc.vid2Locations[vid] = append(locations, location) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
func (vc *vidMap) deleteLocation(vid uint32, location Location) { |
||||
|
vc.Lock() |
||||
|
defer vc.Unlock() |
||||
|
|
||||
|
locations, found := vc.vid2Locations[vid] |
||||
|
if !found { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
for i, loc := range locations { |
||||
|
if loc.Url == location.Url { |
||||
|
vc.vid2Locations[vid] = append(locations[0:i], locations[i+1:]...) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
package wdclient |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
) |
||||
|
|
||||
|
type SeaweedClient struct { |
||||
|
*MasterClient |
||||
|
} |
||||
|
|
||||
|
func NewSeaweedClient(ctx context.Context, clientName string, masters []string) *SeaweedClient { |
||||
|
return &SeaweedClient{ |
||||
|
MasterClient: NewMasterClient(ctx, clientName, masters), |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue