summaryrefslogtreecommitdiff
path: root/db/repl.h
blob: f6b8dc97e34a7bdd001e07cadcd1c6582e46f95e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// repl.h - replication

/**
*    Copyright (C) 2008 10gen Inc.
*  
*    This program is free software: you can redistribute it and/or  modify
*    it under the terms of the GNU Affero General Public License, version 3,
*    as published by the Free Software Foundation.
*  
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU Affero General Public License for more details.
*  
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/* replication data overview

   at the slave: 
     local.sources { host: ..., source: ..., syncedTo: ..., dbs: { ... } }

   at the master:
     local.oplog.$<source>
     local.oplog.$main is the default
*/

#pragma once

class DBClientConnection;
class DBClientCursor;
extern bool slave;
extern bool master;

bool cloneFrom(const char *masterHost, string& errmsg, const string& fromdb);

#pragma pack(push,4)
class OpTime { 
	unsigned i;
	unsigned secs;
public:
    unsigned getSecs() const { return secs; }
	OpTime(unsigned long long date) { 
		reinterpret_cast<unsigned long long&>(*this) = date;
	}
	OpTime(unsigned a, unsigned b) { secs = a; i = b; }
	OpTime() { secs = 0; i = 0; }
	static OpTime now();

	  /* We store OpTime's in the database as Javascript Date datatype -- we needed some sort of 
	     64 bit "container" for these values.  While these are not really "Dates", that seems a 
		 better choice for now than say, Number, which is floating point.  Note the BinData type 
		 is perhaps the cleanest choice, lacking a true unsigned64 datatype, but BinData has a 
		 couple bytes of overhead.
	  */
	  unsigned long long asDate() const { return *((unsigned long long *) &i); } 
//	  unsigned long long& asDate() { return *((unsigned long long *) &i); } 

	  bool isNull() { return secs == 0; }
	  string toString() const { 
		  stringstream ss;
		  ss << hex << secs << ':' << i;
		  return ss.str();
	  }
	  bool operator==(const OpTime& r) const { 
		  return i == r.i && secs == r.secs;
	  }
	  bool operator!=(const OpTime& r) const { return !(*this == r); }
	  bool operator<(const OpTime& r) const { 
		  if( secs != r.secs ) 
			  return secs < r.secs;
		  return i < r.i;
	  }
};
#pragma pack(pop)

/* A replication exception */
struct SyncException { 
};

/* A Source is a source from which we can pull (replicate) data.
   stored in collection local.sources.

   Can be a group of things to replicate for several databases.

      { host: ..., source: ..., syncedTo: ..., dbs: { ... } }

   'source' defaults to 'main'; support for multiple source names is 
   not done (always use main for now).
*/
class ReplSource {
	bool resync(string db);
	void sync_pullOpLog();
	void sync_pullOpLog_applyOperation(BSONObj& op);

	auto_ptr<DBClientConnection> conn;
	auto_ptr<DBClientCursor> cursor;

	set<string> addDbNextPass;

	ReplSource();
public:
	bool paired; // --pair in use
	string hostName;    // ip addr or hostname plus optionally, ":<port>" 
	string _sourceName;  // a logical source name.
    string sourceName() const { return _sourceName.empty() ? "main" : _sourceName; }
	string only; // only a certain db. note that in the sources collection, this may not be changed once you start replicating.

	/* the last time point we have already synced up to. */
	OpTime syncedTo;

	/* list of databases that we have synced. 
	   we need this so that if we encounter a new one, we know 
	   to go fetch the old data.
	*/
	set<string> dbs;

	int nClonedThisPass;

	static void loadAll(vector<ReplSource*>&);
	static void cleanup(vector<ReplSource*>&);
	ReplSource(BSONObj);
	bool sync();
	void save(); // write ourself to local.sources
	void resetConnection() { 
        conn = auto_ptr<DBClientConnection>(0); 
        cursor = auto_ptr<DBClientCursor>(0);
    }

	// make a jsobj from our member fields of the form 
	//   { host: ..., source: ..., syncedTo: ... }
	BSONObj jsobj(); 
	
	bool operator==(const ReplSource&r) const { 
		return hostName == r.hostName && sourceName() == r.sourceName(); 
	}
};

/* Write operation to the log (local.oplog.$main)
   "i" insert
   "u" update
   "d" delete
   "c" db cmd
   "db" declares presence of a database (ns is set to the db name + '.')
*/
void _logOp(const char *opstr, const char *ns, BSONObj& obj, BSONObj *patt, bool *b);
inline void logOp(const char *opstr, const char *ns, BSONObj& obj, BSONObj *patt = 0, bool *b = 0) {
	if( master )
		_logOp(opstr, ns, obj, patt, b);
}