-
Notifications
You must be signed in to change notification settings - Fork 16
/
node.go
162 lines (138 loc) · 3.45 KB
/
node.go
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
152
153
154
155
156
157
158
159
160
161
162
// Copyright (c) 2017-2018 The qitmeer developers
package node
import (
"github.com/Qitmeer/qng/common/roughtime"
"github.com/Qitmeer/qng/common/system"
"github.com/Qitmeer/qng/config"
"github.com/Qitmeer/qng/consensus"
"github.com/Qitmeer/qng/consensus/model"
"github.com/Qitmeer/qng/core/event"
"github.com/Qitmeer/qng/database"
"github.com/Qitmeer/qng/node/service"
"github.com/Qitmeer/qng/params"
"github.com/gofrs/flock"
"os"
"path/filepath"
"sync"
)
// Node works as a server container for all service can be registered.
// such as p2p, rpc, ws etc.
type Node struct {
service.Service
lock sync.RWMutex
startupTime int64
// config
Config *config.Config
Params *params.Params
// database layer
DB model.DataBase
dirLock *flock.Flock // prevents concurrent use of instance directory
interrupt <-chan struct{}
consensus model.Consensus
}
func NewNode(cfg *config.Config, chainParams *params.Params, interrupt <-chan struct{}) (*Node, error) {
n := Node{
Config: cfg,
Params: chainParams,
interrupt: interrupt,
}
n.InitServices()
// Acquire the instance directory lock.
if err := n.openDataDir(); err != nil {
return nil, err
}
return &n, nil
}
func (n *Node) Stop() error {
n.lock.Lock()
defer n.lock.Unlock()
log.Info("Stopping Server")
if err := n.Service.Stop(); err != nil {
return err
}
n.DB.Close()
// Release instance directory lock.
n.closeDataDir()
return nil
}
func (n *Node) Start() error {
n.lock.Lock()
defer n.lock.Unlock()
log.Info("Starting Node")
// Already started?
if err := n.Service.Start(); err != nil {
return err
}
// Finished node start
// Server startup time. Used for the uptime command for uptime calculation.
n.startupTime = roughtime.Now().Unix()
n.consensus.Events().Send(event.New(event.Initialized))
return nil
}
func (n *Node) RegisterService() error {
chainDB, err := database.New(n.Config, n.interrupt)
if err != nil {
return err
}
n.DB = chainDB
if chainDB == nil {
return ErrNodeNoDB
}
n.consensus = consensus.New(n.Config, n.DB, n.interrupt, system.ShutdownRequestChannel)
if n.Config.LightNode {
return n.registerQitmeerLight()
}
return n.registerQitmeerFull()
}
// register services as qitmeer Full node
func (n *Node) registerQitmeerFull() error {
fullNode, err := newQitmeerFullNode(n)
if err != nil {
return err
}
n.Services().RegisterService(fullNode)
return nil
}
// register services as the qitmeer Light node
func (n *Node) registerQitmeerLight() error {
lightNode, err := newQitmeerLight(n)
if err != nil {
return err
}
n.Services().RegisterService(lightNode)
return nil
}
// return qitmeer full
func (n *Node) GetQitmeerFull() *QitmeerFull {
var qm *QitmeerFull
if err := n.Services().FetchService(&qm); err != nil {
log.Error(err.Error())
return nil
}
return qm
}
func (n *Node) openDataDir() error {
if n.Config.DataDir == "" {
return nil // ephemeral
}
instdir := n.Config.DataDir
if err := os.MkdirAll(instdir, 0700); err != nil {
return err
}
// Lock the instance directory to prevent concurrent use by another instance as well as
// accidental use of the instance directory as a database.
n.dirLock = flock.New(filepath.Join(instdir, "LOCK"))
if locked, err := n.dirLock.TryLock(); err != nil {
return err
} else if !locked {
return ErrDatadirUsed
}
return nil
}
func (n *Node) closeDataDir() {
// Release instance directory lock.
if n.dirLock != nil && n.dirLock.Locked() {
n.dirLock.Unlock()
n.dirLock = nil
}
}