2012-08-23 22:33:37 -07:00
package topology
import (
2014-10-26 11:34:55 -07:00
"errors"
2019-04-21 10:14:17 -07:00
"fmt"
2014-10-26 11:34:55 -07:00
"math/rand"
2019-05-23 23:34:29 -07:00
"sync"
2014-10-26 11:34:55 -07:00
2015-05-03 12:37:49 -07:00
"github.com/chrislusf/raft"
2016-06-02 18:09:14 -07:00
"github.com/chrislusf/seaweedfs/weed/glog"
2018-07-11 02:01:33 -07:00
"github.com/chrislusf/seaweedfs/weed/pb/master_pb"
2016-06-02 18:09:14 -07:00
"github.com/chrislusf/seaweedfs/weed/sequence"
"github.com/chrislusf/seaweedfs/weed/storage"
2019-04-18 21:43:36 -07:00
"github.com/chrislusf/seaweedfs/weed/storage/needle"
2016-06-02 18:09:14 -07:00
"github.com/chrislusf/seaweedfs/weed/util"
2012-08-23 22:33:37 -07:00
)
type Topology struct {
2019-07-21 21:49:10 -07:00
vacuumLockCounter int64
2012-09-02 14:33:48 -07:00
NodeImpl
2012-09-10 00:18:07 -07:00
2019-05-23 23:34:29 -07:00
collectionMap * util . ConcurrentReadMap
ecShardMap map [ needle . VolumeId ] * EcShardLocations
ecShardMapLock sync . RWMutex
2012-09-10 00:18:07 -07:00
pulse int64
volumeSizeLimit uint64
2014-04-16 23:43:27 -07:00
Sequence sequence . Sequencer
2012-09-18 14:05:12 -07:00
2017-01-10 01:01:12 -08:00
chanFullVolumes chan storage . VolumeInfo
2012-09-24 02:01:53 -07:00
2017-01-10 01:01:12 -08:00
Configuration * Configuration
2014-03-15 23:03:49 -07:00
RaftServer raft . Server
2012-08-31 01:35:11 -07:00
}
2012-08-28 01:04:39 -07:00
2017-02-12 21:58:44 -08:00
func NewTopology ( id string , seq sequence . Sequencer , volumeSizeLimit uint64 , pulse int ) * Topology {
2012-09-02 14:33:48 -07:00
t := & Topology { }
t . id = NodeId ( id )
t . nodeType = "Topology"
2012-09-19 01:45:30 -07:00
t . NodeImpl . value = t
2012-09-02 14:33:48 -07:00
t . children = make ( map [ NodeId ] Node )
2014-12-08 20:29:25 -08:00
t . collectionMap = util . NewConcurrentReadMap ( )
2019-05-23 23:34:29 -07:00
t . ecShardMap = make ( map [ needle . VolumeId ] * EcShardLocations )
2012-09-10 00:18:07 -07:00
t . pulse = int64 ( pulse )
t . volumeSizeLimit = volumeSizeLimit
2012-09-19 01:45:30 -07:00
2014-04-16 23:43:27 -07:00
t . Sequence = seq
2012-09-19 01:45:30 -07:00
2012-12-03 20:28:12 -08:00
t . chanFullVolumes = make ( chan storage . VolumeInfo )
2012-09-19 01:45:30 -07:00
2017-02-12 21:58:44 -08:00
t . Configuration = & Configuration { }
2012-09-24 02:01:53 -07:00
2017-02-12 21:58:44 -08:00
return t
2012-09-02 14:33:48 -07:00
}
2012-09-16 17:31:15 -07:00
2014-03-15 23:03:49 -07:00
func ( t * Topology ) IsLeader ( ) bool {
2019-02-15 00:09:48 -08:00
if t . RaftServer != nil {
2019-01-28 10:36:16 -08:00
return t . RaftServer . State ( ) == raft . Leader
}
2014-04-11 16:23:58 -07:00
return false
2014-03-15 23:03:49 -07:00
}
2014-04-11 16:23:58 -07:00
func ( t * Topology ) Leader ( ) ( string , error ) {
2014-03-15 23:03:49 -07:00
l := ""
if t . RaftServer != nil {
l = t . RaftServer . Leader ( )
2014-04-11 16:23:58 -07:00
} else {
return "" , errors . New ( "Raft Server not ready yet!" )
2014-03-15 23:03:49 -07:00
}
if l == "" {
// We are a single node cluster, we are the leader
2014-04-11 16:23:58 -07:00
return t . RaftServer . Name ( ) , errors . New ( "Raft Server not initialized!" )
2014-03-15 23:03:49 -07:00
}
2014-04-11 16:23:58 -07:00
return l , nil
2014-03-15 23:03:49 -07:00
}
2019-06-05 23:20:26 -07:00
func ( t * Topology ) Lookup ( collection string , vid needle . VolumeId ) ( dataNodes [ ] * DataNode ) {
2013-11-12 02:21:22 -08:00
//maybe an issue if lots of collections?
if collection == "" {
2016-05-30 12:30:26 -07:00
for _ , c := range t . collectionMap . Items ( ) {
2014-12-08 20:29:25 -08:00
if list := c . ( * Collection ) . Lookup ( vid ) ; list != nil {
2012-09-24 02:01:53 -07:00
return list
}
}
2013-11-12 02:21:22 -08:00
} else {
2016-05-30 12:30:26 -07:00
if c , ok := t . collectionMap . Find ( collection ) ; ok {
2014-12-08 20:29:25 -08:00
return c . ( * Collection ) . Lookup ( vid )
2013-11-12 02:21:22 -08:00
}
2012-09-24 02:01:53 -07:00
}
2019-06-05 23:20:26 -07:00
if locations , found := t . LookupEcShards ( vid ) ; found {
for _ , loc := range locations . Locations {
dataNodes = append ( dataNodes , loc ... )
}
return dataNodes
}
2012-09-24 02:01:53 -07:00
return nil
2012-09-23 15:45:26 -07:00
}
2019-04-18 21:43:36 -07:00
func ( t * Topology ) NextVolumeId ( ) ( needle . VolumeId , error ) {
2012-09-02 14:33:48 -07:00
vid := t . GetMaxVolumeId ( )
2014-03-15 23:03:49 -07:00
next := vid . Next ( )
2019-02-25 10:47:41 +08:00
if _ , err := t . RaftServer . Do ( NewMaxVolumeIdCommand ( next ) ) ; err != nil {
return 0 , err
}
return next , nil
2012-08-28 01:04:39 -07:00
}
2012-09-10 00:18:07 -07:00
2014-10-25 23:45:31 -07:00
func ( t * Topology ) HasWritableVolume ( option * VolumeGrowOption ) bool {
2014-09-20 12:38:59 -07:00
vl := t . GetVolumeLayout ( option . Collection , option . ReplicaPlacement , option . Ttl )
2014-04-13 01:29:52 -07:00
return vl . GetActiveVolumeCount ( option ) > 0
}
2015-04-06 14:17:36 -07:00
func ( t * Topology ) PickForWrite ( count uint64 , option * VolumeGrowOption ) ( string , uint64 , * DataNode , error ) {
2014-09-20 12:38:59 -07:00
vid , count , datanodes , err := t . GetVolumeLayout ( option . Collection , option . ReplicaPlacement , option . Ttl ) . PickForWrite ( count , option )
2019-04-21 10:14:17 -07:00
if err != nil {
2019-10-29 21:28:28 +08:00
return "" , 0 , nil , fmt . Errorf ( "failed to find writable volumes for collection:%s replication:%s ttl:%s error: %v" , option . Collection , option . ReplicaPlacement . String ( ) , option . Ttl . String ( ) , err )
2019-04-21 10:14:17 -07:00
}
if datanodes . Length ( ) == 0 {
2019-10-29 21:28:28 +08:00
return "" , 0 , nil , fmt . Errorf ( "no writable volumes available for collection:%s replication:%s ttl:%s" , option . Collection , option . ReplicaPlacement . String ( ) , option . Ttl . String ( ) )
2012-09-16 17:31:15 -07:00
}
2019-10-30 15:49:58 +08:00
fileId := t . Sequence . NextFileId ( count )
2019-04-18 21:43:36 -07:00
return needle . NewFileId ( * vid , fileId , rand . Uint32 ( ) ) . String ( ) , count , datanodes . Head ( ) , nil
2012-09-16 17:31:15 -07:00
}
2019-04-18 21:43:36 -07:00
func ( t * Topology ) GetVolumeLayout ( collectionName string , rp * storage . ReplicaPlacement , ttl * needle . TTL ) * VolumeLayout {
2014-12-08 20:29:25 -08:00
return t . collectionMap . Get ( collectionName , func ( ) interface { } {
return NewCollection ( collectionName , t . volumeSizeLimit )
} ) . ( * Collection ) . GetOrCreateVolumeLayout ( rp , ttl )
2012-09-14 01:17:13 -07:00
}
2019-05-30 09:27:23 -07:00
func ( t * Topology ) ListCollections ( includeNormalVolumes , includeEcVolumes bool ) ( ret [ ] string ) {
2019-05-30 09:17:58 -07:00
mapOfCollections := make ( map [ string ] bool )
2019-03-16 13:43:16 -07:00
for _ , c := range t . collectionMap . Items ( ) {
2019-05-30 09:17:58 -07:00
mapOfCollections [ c . ( * Collection ) . Name ] = true
}
2019-05-30 09:27:23 -07:00
if includeEcVolumes {
t . ecShardMapLock . RLock ( )
for _ , ecVolumeLocation := range t . ecShardMap {
mapOfCollections [ ecVolumeLocation . Collection ] = true
}
t . ecShardMapLock . RUnlock ( )
2019-05-30 09:17:58 -07:00
}
for k , _ := range mapOfCollections {
ret = append ( ret , k )
2019-03-16 13:43:16 -07:00
}
return ret
}
2016-05-30 12:30:26 -07:00
func ( t * Topology ) FindCollection ( collectionName string ) ( * Collection , bool ) {
c , hasCollection := t . collectionMap . Find ( collectionName )
2017-07-14 20:04:33 +08:00
if ! hasCollection {
return nil , false
}
2014-12-08 20:29:25 -08:00
return c . ( * Collection ) , hasCollection
2014-03-10 11:43:54 -07:00
}
func ( t * Topology ) DeleteCollection ( collectionName string ) {
2016-05-30 12:30:26 -07:00
t . collectionMap . Delete ( collectionName )
2014-03-10 11:43:54 -07:00
}
2014-03-19 04:48:13 -07:00
func ( t * Topology ) RegisterVolumeLayout ( v storage . VolumeInfo , dn * DataNode ) {
2014-09-20 12:38:59 -07:00
t . GetVolumeLayout ( v . Collection , v . ReplicaPlacement , v . Ttl ) . RegisterVolume ( & v , dn )
}
func ( t * Topology ) UnRegisterVolumeLayout ( v storage . VolumeInfo , dn * DataNode ) {
glog . Infof ( "removing volume info:%+v" , v )
2018-07-11 02:01:33 -07:00
volumeLayout := t . GetVolumeLayout ( v . Collection , v . ReplicaPlacement , v . Ttl )
volumeLayout . UnRegisterVolume ( & v , dn )
if volumeLayout . isEmpty ( ) {
t . DeleteCollection ( v . Collection )
}
2012-09-16 17:31:15 -07:00
}
2012-09-22 20:46:31 -07:00
func ( t * Topology ) GetOrCreateDataCenter ( dcName string ) * DataCenter {
2012-09-16 17:31:15 -07:00
for _ , c := range t . Children ( ) {
dc := c . ( * DataCenter )
2012-09-22 20:46:31 -07:00
if string ( dc . Id ( ) ) == dcName {
2012-09-16 17:31:15 -07:00
return dc
}
}
2012-09-22 20:46:31 -07:00
dc := NewDataCenter ( dcName )
2012-09-16 17:31:15 -07:00
t . LinkChildNode ( dc )
return dc
}
2018-06-25 00:01:53 -07:00
2018-07-27 23:09:55 -07:00
func ( t * Topology ) SyncDataNodeRegistration ( volumes [ ] * master_pb . VolumeInformationMessage , dn * DataNode ) ( newVolumes , deletedVolumes [ ] storage . VolumeInfo ) {
2019-05-23 00:04:24 -07:00
// convert into in memory struct storage.VolumeInfo
2018-06-25 00:01:53 -07:00
var volumeInfos [ ] storage . VolumeInfo
for _ , v := range volumes {
if vi , err := storage . NewVolumeInfo ( v ) ; err == nil {
volumeInfos = append ( volumeInfos , vi )
} else {
glog . V ( 0 ) . Infof ( "Fail to convert joined volume information: %v" , err )
}
}
2019-05-23 00:04:24 -07:00
// find out the delta volumes
2018-07-27 23:09:55 -07:00
newVolumes , deletedVolumes = dn . UpdateVolumes ( volumeInfos )
2019-04-20 11:35:20 -07:00
for _ , v := range newVolumes {
2018-06-25 00:01:53 -07:00
t . RegisterVolumeLayout ( v , dn )
}
for _ , v := range deletedVolumes {
t . UnRegisterVolumeLayout ( v , dn )
}
2018-07-27 23:09:55 -07:00
return
2018-06-25 00:01:53 -07:00
}
2019-04-20 11:35:20 -07:00
func ( t * Topology ) IncrementalSyncDataNodeRegistration ( newVolumes , deletedVolumes [ ] * master_pb . VolumeShortInformationMessage , dn * DataNode ) {
var newVis , oldVis [ ] storage . VolumeInfo
for _ , v := range newVolumes {
vi , err := storage . NewVolumeInfoFromShort ( v )
if err != nil {
glog . V ( 0 ) . Infof ( "NewVolumeInfoFromShort %v: %v" , v , err )
continue
}
newVis = append ( newVis , vi )
}
for _ , v := range deletedVolumes {
vi , err := storage . NewVolumeInfoFromShort ( v )
if err != nil {
glog . V ( 0 ) . Infof ( "NewVolumeInfoFromShort %v: %v" , v , err )
continue
}
oldVis = append ( oldVis , vi )
}
dn . DeltaUpdateVolumes ( newVis , oldVis )
2019-04-20 23:53:37 -07:00
for _ , vi := range newVis {
t . RegisterVolumeLayout ( vi , dn )
}
for _ , vi := range oldVis {
t . UnRegisterVolumeLayout ( vi , dn )
}
2019-04-20 11:35:20 -07:00
return
}