PageRenderTime 77ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/src/github.com/docker/libnetwork/networkdb/networkdb.go

https://gitlab.com/0072016/0072016-docker
Go | 451 lines | 279 code | 84 blank | 88 comment | 44 complexity | 8ea9b84de609a972db4510b12f6d6897 MD5 | raw file
  1. package networkdb
  2. //go:generate protoc -I.:../Godeps/_workspace/src/github.com/gogo/protobuf --gogo_out=import_path=github.com/docker/libnetwork/networkdb,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto:. networkdb.proto
  3. import (
  4. "fmt"
  5. "strings"
  6. "sync"
  7. "time"
  8. "github.com/Sirupsen/logrus"
  9. "github.com/armon/go-radix"
  10. "github.com/docker/go-events"
  11. "github.com/hashicorp/memberlist"
  12. "github.com/hashicorp/serf/serf"
  13. )
  14. const (
  15. byTable int = 1 + iota
  16. byNetwork
  17. )
  18. // NetworkDB instance drives the networkdb cluster and acts the broker
  19. // for cluster-scoped and network-scoped gossip and watches.
  20. type NetworkDB struct {
  21. sync.RWMutex
  22. // NetworkDB configuration.
  23. config *Config
  24. // local copy of memberlist config that we use to driver
  25. // network scoped gossip and bulk sync.
  26. mConfig *memberlist.Config
  27. // All the tree index (byTable, byNetwork) that we maintain
  28. // the db.
  29. indexes map[int]*radix.Tree
  30. // Memberlist we use to drive the cluster.
  31. memberlist *memberlist.Memberlist
  32. // List of all peer nodes in the cluster not-limited to any
  33. // network.
  34. nodes map[string]*memberlist.Node
  35. // A multi-dimensional map of network/node attachmemts. The
  36. // first key is a node name and the second key is a network ID
  37. // for the network that node is participating in.
  38. networks map[string]map[string]*network
  39. // A map of nodes which are participating in a given
  40. // network. The key is a network ID.
  41. networkNodes map[string][]string
  42. // A table of ack channels for every node from which we are
  43. // waiting for an ack.
  44. bulkSyncAckTbl map[string]chan struct{}
  45. // Global lamport clock for node network attach events.
  46. networkClock serf.LamportClock
  47. // Global lamport clock for table events.
  48. tableClock serf.LamportClock
  49. // Broadcast queue for network event gossip.
  50. networkBroadcasts *memberlist.TransmitLimitedQueue
  51. // A central stop channel to stop all go routines running on
  52. // behalf of the NetworkDB instance.
  53. stopCh chan struct{}
  54. // A central broadcaster for all local watchers watching table
  55. // events.
  56. broadcaster *events.Broadcaster
  57. // List of all tickers which needed to be stopped when
  58. // cleaning up.
  59. tickers []*time.Ticker
  60. // Reference to the memberlist's keyring to add & remove keys
  61. keyring *memberlist.Keyring
  62. }
  63. // network describes the node/network attachment.
  64. type network struct {
  65. // Network ID
  66. id string
  67. // Lamport time for the latest state of the entry.
  68. ltime serf.LamportTime
  69. // Node leave is in progress.
  70. leaving bool
  71. // The time this node knew about the node's network leave.
  72. leaveTime time.Time
  73. // The broadcast queue for table event gossip. This is only
  74. // initialized for this node's network attachment entries.
  75. tableBroadcasts *memberlist.TransmitLimitedQueue
  76. }
  77. // Config represents the configuration of the networdb instance and
  78. // can be passed by the caller.
  79. type Config struct {
  80. // NodeName is the cluster wide unique name for this node.
  81. NodeName string
  82. // AdvertiseAddr is the node's IP address that we advertise for
  83. // cluster communication.
  84. AdvertiseAddr string
  85. // BindPort is the local node's port to which we bind to for
  86. // cluster communication.
  87. BindPort int
  88. // Keys to be added to the Keyring of the memberlist. Key at index
  89. // 0 is the primary key
  90. Keys [][]byte
  91. }
  92. // entry defines a table entry
  93. type entry struct {
  94. // node from which this entry was learned.
  95. node string
  96. // Lamport time for the most recent update to the entry
  97. ltime serf.LamportTime
  98. // Opaque value store in the entry
  99. value []byte
  100. // Deleting the entry is in progress. All entries linger in
  101. // the cluster for certain amount of time after deletion.
  102. deleting bool
  103. // The wall clock time when this node learned about this deletion.
  104. deleteTime time.Time
  105. }
  106. // New creates a new instance of NetworkDB using the Config passed by
  107. // the caller.
  108. func New(c *Config) (*NetworkDB, error) {
  109. nDB := &NetworkDB{
  110. config: c,
  111. indexes: make(map[int]*radix.Tree),
  112. networks: make(map[string]map[string]*network),
  113. nodes: make(map[string]*memberlist.Node),
  114. networkNodes: make(map[string][]string),
  115. bulkSyncAckTbl: make(map[string]chan struct{}),
  116. broadcaster: events.NewBroadcaster(),
  117. }
  118. nDB.indexes[byTable] = radix.New()
  119. nDB.indexes[byNetwork] = radix.New()
  120. if err := nDB.clusterInit(); err != nil {
  121. return nil, err
  122. }
  123. return nDB, nil
  124. }
  125. // Join joins this NetworkDB instance with a list of peer NetworkDB
  126. // instances passed by the caller in the form of addr:port
  127. func (nDB *NetworkDB) Join(members []string) error {
  128. return nDB.clusterJoin(members)
  129. }
  130. // Close destroys this NetworkDB instance by leave the cluster,
  131. // stopping timers, canceling goroutines etc.
  132. func (nDB *NetworkDB) Close() {
  133. if err := nDB.clusterLeave(); err != nil {
  134. logrus.Errorf("Could not close DB %s: %v", nDB.config.NodeName, err)
  135. }
  136. }
  137. // GetEntry retrieves the value of a table entry in a given (network,
  138. // table, key) tuple
  139. func (nDB *NetworkDB) GetEntry(tname, nid, key string) ([]byte, error) {
  140. entry, err := nDB.getEntry(tname, nid, key)
  141. if err != nil {
  142. return nil, err
  143. }
  144. return entry.value, nil
  145. }
  146. func (nDB *NetworkDB) getEntry(tname, nid, key string) (*entry, error) {
  147. nDB.RLock()
  148. defer nDB.RUnlock()
  149. e, ok := nDB.indexes[byTable].Get(fmt.Sprintf("/%s/%s/%s", tname, nid, key))
  150. if !ok {
  151. return nil, fmt.Errorf("could not get entry in table %s with network id %s and key %s", tname, nid, key)
  152. }
  153. return e.(*entry), nil
  154. }
  155. // CreateEntry creates a table entry in NetworkDB for given (network,
  156. // table, key) tuple and if the NetworkDB is part of the cluster
  157. // propogates this event to the cluster. It is an error to create an
  158. // entry for the same tuple for which there is already an existing
  159. // entry.
  160. func (nDB *NetworkDB) CreateEntry(tname, nid, key string, value []byte) error {
  161. if _, err := nDB.GetEntry(tname, nid, key); err == nil {
  162. return fmt.Errorf("cannot create entry as the entry in table %s with network id %s and key %s already exists", tname, nid, key)
  163. }
  164. entry := &entry{
  165. ltime: nDB.tableClock.Increment(),
  166. node: nDB.config.NodeName,
  167. value: value,
  168. }
  169. if err := nDB.sendTableEvent(TableEventTypeCreate, nid, tname, key, entry); err != nil {
  170. return fmt.Errorf("cannot send table create event: %v", err)
  171. }
  172. nDB.Lock()
  173. nDB.indexes[byTable].Insert(fmt.Sprintf("/%s/%s/%s", tname, nid, key), entry)
  174. nDB.indexes[byNetwork].Insert(fmt.Sprintf("/%s/%s/%s", nid, tname, key), entry)
  175. nDB.Unlock()
  176. nDB.broadcaster.Write(makeEvent(opCreate, tname, nid, key, value))
  177. return nil
  178. }
  179. // UpdateEntry updates a table entry in NetworkDB for given (network,
  180. // table, key) tuple and if the NetworkDB is part of the cluster
  181. // propogates this event to the cluster. It is an error to update a
  182. // non-existent entry.
  183. func (nDB *NetworkDB) UpdateEntry(tname, nid, key string, value []byte) error {
  184. if _, err := nDB.GetEntry(tname, nid, key); err != nil {
  185. return fmt.Errorf("cannot update entry as the entry in table %s with network id %s and key %s does not exist", tname, nid, key)
  186. }
  187. entry := &entry{
  188. ltime: nDB.tableClock.Increment(),
  189. node: nDB.config.NodeName,
  190. value: value,
  191. }
  192. if err := nDB.sendTableEvent(TableEventTypeUpdate, nid, tname, key, entry); err != nil {
  193. return fmt.Errorf("cannot send table update event: %v", err)
  194. }
  195. nDB.Lock()
  196. nDB.indexes[byTable].Insert(fmt.Sprintf("/%s/%s/%s", tname, nid, key), entry)
  197. nDB.indexes[byNetwork].Insert(fmt.Sprintf("/%s/%s/%s", nid, tname, key), entry)
  198. nDB.Unlock()
  199. nDB.broadcaster.Write(makeEvent(opUpdate, tname, nid, key, value))
  200. return nil
  201. }
  202. // DeleteEntry deletes a table entry in NetworkDB for given (network,
  203. // table, key) tuple and if the NetworkDB is part of the cluster
  204. // propogates this event to the cluster.
  205. func (nDB *NetworkDB) DeleteEntry(tname, nid, key string) error {
  206. value, err := nDB.GetEntry(tname, nid, key)
  207. if err != nil {
  208. return fmt.Errorf("cannot delete entry as the entry in table %s with network id %s and key %s does not exist", tname, nid, key)
  209. }
  210. entry := &entry{
  211. ltime: nDB.tableClock.Increment(),
  212. node: nDB.config.NodeName,
  213. value: value,
  214. deleting: true,
  215. deleteTime: time.Now(),
  216. }
  217. if err := nDB.sendTableEvent(TableEventTypeDelete, nid, tname, key, entry); err != nil {
  218. return fmt.Errorf("cannot send table delete event: %v", err)
  219. }
  220. nDB.Lock()
  221. nDB.indexes[byTable].Insert(fmt.Sprintf("/%s/%s/%s", tname, nid, key), entry)
  222. nDB.indexes[byNetwork].Insert(fmt.Sprintf("/%s/%s/%s", nid, tname, key), entry)
  223. nDB.Unlock()
  224. nDB.broadcaster.Write(makeEvent(opDelete, tname, nid, key, value))
  225. return nil
  226. }
  227. func (nDB *NetworkDB) deleteNetworkNodeEntries(deletedNode string) {
  228. nDB.Lock()
  229. for nid, nodes := range nDB.networkNodes {
  230. updatedNodes := make([]string, 0, len(nodes))
  231. for _, node := range nodes {
  232. if node == deletedNode {
  233. continue
  234. }
  235. updatedNodes = append(updatedNodes, node)
  236. }
  237. nDB.networkNodes[nid] = updatedNodes
  238. }
  239. nDB.Unlock()
  240. }
  241. func (nDB *NetworkDB) deleteNodeTableEntries(node string) {
  242. nDB.Lock()
  243. nDB.indexes[byTable].Walk(func(path string, v interface{}) bool {
  244. oldEntry := v.(*entry)
  245. if oldEntry.node != node {
  246. return false
  247. }
  248. params := strings.Split(path[1:], "/")
  249. tname := params[0]
  250. nid := params[1]
  251. key := params[2]
  252. entry := &entry{
  253. ltime: oldEntry.ltime,
  254. node: node,
  255. value: oldEntry.value,
  256. deleting: true,
  257. deleteTime: time.Now(),
  258. }
  259. nDB.indexes[byTable].Insert(fmt.Sprintf("/%s/%s/%s", tname, nid, key), entry)
  260. nDB.indexes[byNetwork].Insert(fmt.Sprintf("/%s/%s/%s", nid, tname, key), entry)
  261. return false
  262. })
  263. nDB.Unlock()
  264. }
  265. // WalkTable walks a single table in NetworkDB and invokes the passed
  266. // function for each entry in the table passing the network, key,
  267. // value. The walk stops if the passed function returns a true.
  268. func (nDB *NetworkDB) WalkTable(tname string, fn func(string, string, []byte) bool) error {
  269. nDB.RLock()
  270. values := make(map[string]interface{})
  271. nDB.indexes[byTable].WalkPrefix(fmt.Sprintf("/%s", tname), func(path string, v interface{}) bool {
  272. values[path] = v
  273. return false
  274. })
  275. nDB.RUnlock()
  276. for k, v := range values {
  277. params := strings.Split(k[1:], "/")
  278. nid := params[1]
  279. key := params[2]
  280. if fn(nid, key, v.(*entry).value) {
  281. return nil
  282. }
  283. }
  284. return nil
  285. }
  286. // JoinNetwork joins this node to a given network and propogates this
  287. // event across the cluster. This triggers this node joining the
  288. // sub-cluster of this network and participates in the network-scoped
  289. // gossip and bulk sync for this network.
  290. func (nDB *NetworkDB) JoinNetwork(nid string) error {
  291. ltime := nDB.networkClock.Increment()
  292. nDB.Lock()
  293. nodeNetworks, ok := nDB.networks[nDB.config.NodeName]
  294. if !ok {
  295. nodeNetworks = make(map[string]*network)
  296. nDB.networks[nDB.config.NodeName] = nodeNetworks
  297. }
  298. nodeNetworks[nid] = &network{id: nid, ltime: ltime}
  299. nodeNetworks[nid].tableBroadcasts = &memberlist.TransmitLimitedQueue{
  300. NumNodes: func() int {
  301. return len(nDB.networkNodes[nid])
  302. },
  303. RetransmitMult: 4,
  304. }
  305. nDB.networkNodes[nid] = append(nDB.networkNodes[nid], nDB.config.NodeName)
  306. networkNodes := nDB.networkNodes[nid]
  307. nDB.Unlock()
  308. if err := nDB.sendNetworkEvent(nid, NetworkEventTypeJoin, ltime); err != nil {
  309. return fmt.Errorf("failed to send leave network event for %s: %v", nid, err)
  310. }
  311. logrus.Debugf("%s: joined network %s", nDB.config.NodeName, nid)
  312. if _, err := nDB.bulkSync(nid, networkNodes, true); err != nil {
  313. logrus.Errorf("Error bulk syncing while joining network %s: %v", nid, err)
  314. }
  315. return nil
  316. }
  317. // LeaveNetwork leaves this node from a given network and propogates
  318. // this event across the cluster. This triggers this node leaving the
  319. // sub-cluster of this network and as a result will no longer
  320. // participate in the network-scoped gossip and bulk sync for this
  321. // network.
  322. func (nDB *NetworkDB) LeaveNetwork(nid string) error {
  323. ltime := nDB.networkClock.Increment()
  324. if err := nDB.sendNetworkEvent(nid, NetworkEventTypeLeave, ltime); err != nil {
  325. return fmt.Errorf("failed to send leave network event for %s: %v", nid, err)
  326. }
  327. nDB.Lock()
  328. defer nDB.Unlock()
  329. nodeNetworks, ok := nDB.networks[nDB.config.NodeName]
  330. if !ok {
  331. return fmt.Errorf("could not find self node for network %s while trying to leave", nid)
  332. }
  333. n, ok := nodeNetworks[nid]
  334. if !ok {
  335. return fmt.Errorf("could not find network %s while trying to leave", nid)
  336. }
  337. n.ltime = ltime
  338. n.leaving = true
  339. return nil
  340. }
  341. // Deletes the node from the list of nodes which participate in the
  342. // passed network. Caller should hold the NetworkDB lock while calling
  343. // this
  344. func (nDB *NetworkDB) deleteNetworkNode(nid string, nodeName string) {
  345. nodes := nDB.networkNodes[nid]
  346. for i, name := range nodes {
  347. if name == nodeName {
  348. nodes[i] = nodes[len(nodes)-1]
  349. nodes = nodes[:len(nodes)-1]
  350. break
  351. }
  352. }
  353. nDB.networkNodes[nid] = nodes
  354. }
  355. // findCommonnetworks find the networks that both this node and the
  356. // passed node have joined.
  357. func (nDB *NetworkDB) findCommonNetworks(nodeName string) []string {
  358. nDB.RLock()
  359. defer nDB.RUnlock()
  360. var networks []string
  361. for nid := range nDB.networks[nDB.config.NodeName] {
  362. if _, ok := nDB.networks[nodeName][nid]; ok {
  363. networks = append(networks, nid)
  364. }
  365. }
  366. return networks
  367. }