Skip to content

Commit e98619b

Browse files
author
Tim Vaillancourt
committed
breaking replset/find_secondary apart a bit more
1 parent b13553f commit e98619b

File tree

1 file changed

+36
-21
lines changed

1 file changed

+36
-21
lines changed

MongoBackup/Replset.py

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ def __init__(self, db, user, password, authdb, max_lag_secs):
1515
self.authdb = authdb
1616
self.max_lag_secs = max_lag_secs
1717

18+
self.rs_status = None
19+
self.primary = None
20+
self.secondary = None
21+
1822
# Get a DB connection
1923
try:
2024
if self.db.__class__.__name__ == "DB":
@@ -28,9 +32,11 @@ def __init__(self, db, user, password, authdb, max_lag_secs):
2832
def close(self):
2933
pass
3034

31-
def get_rs_status(self):
35+
def get_rs_status(self, force=False):
3236
try:
33-
return self.db.admin_command('replSetGetStatus')
37+
if force or not self.rs_status:
38+
self.rs_status = self.db.admin_command('replSetGetStatus')
39+
return self.rs_status
3440
except Exception, e:
3541
raise Exception, "Error getting replica set status! Error: %s" % e, None
3642

@@ -44,16 +50,12 @@ def get_rs_config(self):
4450
except Exception, e:
4551
raise Exception, "Error getting replica set config! Error: %s" % e, None
4652

47-
def find_secondary(self):
48-
rs_status = self.get_rs_status()
49-
rs_config = self.get_rs_config()
50-
rs_name = rs_status['set']
51-
quorum_count = ceil(len(rs_status['members']) / 2.0)
52-
53-
primary = None
53+
def find_primary(self):
54+
rs_status = self.get_rs_status()
55+
rs_name = rs_status['set']
5456
for member in rs_status['members']:
5557
if member['stateStr'] == 'PRIMARY' and member['health'] > 0:
56-
primary = {
58+
self.primary = {
5759
'host': member['name'],
5860
'optime': member['optimeDate']
5961
}
@@ -65,11 +67,18 @@ def find_secondary(self):
6567
member['name'],
6668
str(optime)
6769
))
68-
if primary is None:
70+
if self.primary is None:
6971
logging.fatal("Unable to locate a PRIMARY member for replset %s, giving up" % rs_name)
7072
raise Exception, "Unable to locate a PRIMARY member for replset %s, giving up" % rs_name, None
71-
72-
secondary = None
73+
return self.primary
74+
75+
def find_secondary(self):
76+
rs_status = self.get_rs_status()
77+
rs_config = self.get_rs_config()
78+
rs_primary = self.find_primary()
79+
rs_name = rs_status['set']
80+
quorum_count = ceil(len(rs_status['members']) / 2.0)
81+
7382
for member in rs_status['members']:
7483
if member['stateStr'] == 'SECONDARY' and member['health'] > 0:
7584
score = self.max_lag_secs * 10
@@ -88,13 +97,13 @@ def find_secondary(self):
8897
score = score - member_config['priority']
8998
break
9099

91-
rep_lag = (mktime(primary['optime'].timetuple()) - mktime(member['optimeDate'].timetuple()))
100+
rep_lag = (mktime(self.primary_optime().timetuple()) - mktime(member['optimeDate'].timetuple()))
92101
score = ceil((score - rep_lag) * score_scale)
93102
if rep_lag < self.max_lag_secs:
94-
if secondary is None or score > secondary['score']:
95-
secondary = {
103+
if self.secondary is None or score > self.secondary['score']:
104+
self.secondary = {
96105
'replSet': rs_name,
97-
'count': 1 if secondary is None else secondary['count'] + 1,
106+
'count': 1 if self.secondary is None else self.secondary['count'] + 1,
98107
'host': member['name'],
99108
'optime': member['optimeDate'],
100109
'score': score
@@ -108,16 +117,22 @@ def find_secondary(self):
108117
log_data['optime'] = member['optime']['ts']
109118
log_data['score'] = int(score)
110119
logging.info("%s: %s" % (log_msg, str(log_data)))
111-
if secondary is None or (secondary['count'] + 1) < quorum_count:
120+
if self.secondary is None or (self.secondary['count'] + 1) < quorum_count:
112121
logging.fatal("Not enough secondaries in replset %s to take backup! Num replset members: %i, required quorum: %i" % (
113122
rs_name,
114-
secondary['count'] + 1,
123+
self.secondary['count'] + 1,
115124
quorum_count
116125
))
117126
raise Exception, "Not enough secondaries in replset %s to safely take backup!" % rs_name, None
118127

119-
logging.info("Choosing SECONDARY %s for replica set %s (score: %i)" % (secondary['host'], rs_name, secondary['score']))
120-
return secondary
128+
logging.info("Choosing SECONDARY %s for replica set %s (score: %i)" % (self.secondary['host'], rs_name, self.secondary['score']))
129+
return self.secondary
130+
131+
def primary_optime(self):
132+
rs_status = self.get_rs_status()
133+
rs_primary = self.find_primary()
134+
if 'optime' in rs_primary:
135+
return rs_primary['optime']
121136

122137

123138
class ReplsetSharded:

0 commit comments

Comments
 (0)