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.
142 lines
3.5 KiB
142 lines
3.5 KiB
// Copyright (C) MongoDB, Inc. 2017-present. |
|
// |
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may |
|
// not use this file except in compliance with the License. You may obtain |
|
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 |
|
|
|
package description |
|
|
|
import ( |
|
"fmt" |
|
|
|
"go.mongodb.org/mongo-driver/mongo/readpref" |
|
) |
|
|
|
// Topology contains information about a MongoDB cluster. |
|
type Topology struct { |
|
Servers []Server |
|
SetName string |
|
Kind TopologyKind |
|
SessionTimeoutMinutes uint32 |
|
CompatibilityErr error |
|
} |
|
|
|
// String implements the Stringer interface. |
|
func (t Topology) String() string { |
|
var serversStr string |
|
for _, s := range t.Servers { |
|
serversStr += "{ " + s.String() + " }, " |
|
} |
|
return fmt.Sprintf("Type: %s, Servers: [%s]", t.Kind, serversStr) |
|
} |
|
|
|
// Equal compares two topology descriptions and returns true if they are equal. |
|
func (t Topology) Equal(other Topology) bool { |
|
if t.Kind != other.Kind { |
|
return false |
|
} |
|
|
|
topoServers := make(map[string]Server) |
|
for _, s := range t.Servers { |
|
topoServers[s.Addr.String()] = s |
|
} |
|
|
|
otherServers := make(map[string]Server) |
|
for _, s := range other.Servers { |
|
otherServers[s.Addr.String()] = s |
|
} |
|
|
|
if len(topoServers) != len(otherServers) { |
|
return false |
|
} |
|
|
|
for _, server := range topoServers { |
|
otherServer := otherServers[server.Addr.String()] |
|
|
|
if !server.Equal(otherServer) { |
|
return false |
|
} |
|
} |
|
|
|
return true |
|
} |
|
|
|
// HasReadableServer returns true if the topology contains a server suitable for reading. |
|
// |
|
// If the Topology's kind is Single or Sharded, the mode parameter is ignored and the function contains true if any of |
|
// the servers in the Topology are of a known type. |
|
// |
|
// For replica sets, the function returns true if the cluster contains a server that matches the provided read |
|
// preference mode. |
|
func (t Topology) HasReadableServer(mode readpref.Mode) bool { |
|
switch t.Kind { |
|
case Single, Sharded: |
|
return hasAvailableServer(t.Servers, 0) |
|
case ReplicaSetWithPrimary: |
|
return hasAvailableServer(t.Servers, mode) |
|
case ReplicaSetNoPrimary, ReplicaSet: |
|
if mode == readpref.PrimaryMode { |
|
return false |
|
} |
|
// invalid read preference |
|
if !mode.IsValid() { |
|
return false |
|
} |
|
|
|
return hasAvailableServer(t.Servers, mode) |
|
} |
|
return false |
|
} |
|
|
|
// HasWritableServer returns true if a topology has a server available for writing. |
|
// |
|
// If the Topology's kind is Single or Sharded, this function returns true if any of the servers in the Topology are of |
|
// a known type. |
|
// |
|
// For replica sets, the function returns true if the replica set contains a primary. |
|
func (t Topology) HasWritableServer() bool { |
|
return t.HasReadableServer(readpref.PrimaryMode) |
|
} |
|
|
|
// hasAvailableServer returns true if any servers are available based on the read preference. |
|
func hasAvailableServer(servers []Server, mode readpref.Mode) bool { |
|
switch mode { |
|
case readpref.PrimaryMode: |
|
for _, s := range servers { |
|
if s.Kind == RSPrimary { |
|
return true |
|
} |
|
} |
|
return false |
|
case readpref.PrimaryPreferredMode, readpref.SecondaryPreferredMode, readpref.NearestMode: |
|
for _, s := range servers { |
|
if s.Kind == RSPrimary || s.Kind == RSSecondary { |
|
return true |
|
} |
|
} |
|
return false |
|
case readpref.SecondaryMode: |
|
for _, s := range servers { |
|
if s.Kind == RSSecondary { |
|
return true |
|
} |
|
} |
|
return false |
|
} |
|
|
|
// read preference is not specified |
|
for _, s := range servers { |
|
switch s.Kind { |
|
case Standalone, |
|
RSMember, |
|
RSPrimary, |
|
RSSecondary, |
|
RSArbiter, |
|
RSGhost, |
|
Mongos: |
|
return true |
|
} |
|
} |
|
|
|
return false |
|
}
|
|
|