Browse Source

Display general information about the state of upstream node

pool
Sammy Libre 7 years ago
parent
commit
a9ae6bf347
  1. 35
      rpc/rpc.go
  2. 1
      stratum/api.go
  3. 29
      stratum/stratum.go
  4. 22
      www/index.html

35
rpc/rpc.go

@ -28,6 +28,7 @@ type RPCClient struct {
Name string Name string
sick bool sick bool
client *http.Client client *http.Client
info atomic.Value
} }
type GetBlockTemplateReply struct { type GetBlockTemplateReply struct {
@ -38,6 +39,14 @@ type GetBlockTemplateReply struct {
PrevHash string `json:"prev_hash"` PrevHash string `json:"prev_hash"`
} }
type GetInfoReply struct {
IncomingConnections int64 `json:"incoming_connections_count"`
OutgoingConnections int64 `json:"outgoing_connections_count"`
Status string `json:"status"`
Height int64 `json:"height"`
TxPoolSize int64 `json:"tx_pool_size"`
}
type JSONRpcResp struct { type JSONRpcResp struct {
Id *json.RawMessage `json:"id"` Id *json.RawMessage `json:"id"`
Result *json.RawMessage `json:"result"` Result *json.RawMessage `json:"result"`
@ -71,6 +80,19 @@ func (r *RPCClient) GetBlockTemplate(reserveSize int, address string) (*GetBlock
return reply, err return reply, err
} }
func (r *RPCClient) GetInfo() (*GetInfoReply, error) {
params := make(map[string]interface{})
rpcResp, err := r.doPost(r.Url.String(), "get_info", params)
var reply *GetInfoReply
if err != nil {
return nil, err
}
if rpcResp.Result != nil {
err = json.Unmarshal(*rpcResp.Result, &reply)
}
return reply, err
}
func (r *RPCClient) SubmitBlock(hash string) (*JSONRpcResp, error) { func (r *RPCClient) SubmitBlock(hash string) (*JSONRpcResp, error) {
return r.doPost(r.Url.String(), "submitblock", []string{hash}) return r.doPost(r.Url.String(), "submitblock", []string{hash})
} }
@ -145,3 +167,16 @@ func (r *RPCClient) markAlive() {
} }
r.Unlock() r.Unlock()
} }
func (r *RPCClient) UpdateInfo() (*GetInfoReply, error) {
info, err := r.GetInfo()
if err == nil {
r.info.Store(info)
}
return info, err
}
func (r *RPCClient) Info() *GetInfoReply {
reply, _ := r.info.Load().(*GetInfoReply)
return reply
}

1
stratum/api.go

@ -58,6 +58,7 @@ func convertUpstream(u *rpc.RPCClient) map[string]interface{} {
"rejects": atomic.LoadInt64(&u.Rejects), "rejects": atomic.LoadInt64(&u.Rejects),
"lastSubmissionAt": atomic.LoadInt64(&u.LastSubmissionAt), "lastSubmissionAt": atomic.LoadInt64(&u.LastSubmissionAt),
"failsCount": atomic.LoadInt64(&u.FailsCount), "failsCount": atomic.LoadInt64(&u.FailsCount),
"info": u.Info(),
} }
return upstream return upstream
} }

29
stratum/stratum.go

@ -100,6 +100,9 @@ func NewStratum(cfg *pool.Config) *StratumServer {
checkIntv, _ := time.ParseDuration(cfg.UpstreamCheckInterval) checkIntv, _ := time.ParseDuration(cfg.UpstreamCheckInterval)
checkTimer := time.NewTimer(checkIntv) checkTimer := time.NewTimer(checkIntv)
infoIntv, _ := time.ParseDuration(cfg.UpstreamCheckInterval)
infoTimer := time.NewTimer(infoIntv)
// Init block template // Init block template
go stratum.refreshBlockTemplate(false) go stratum.refreshBlockTemplate(false)
@ -123,6 +126,32 @@ func NewStratum(cfg *pool.Config) *StratumServer {
} }
}() }()
go func() {
for {
select {
case <-infoTimer.C:
poll := func(v *rpc.RPCClient) {
_, err := v.UpdateInfo()
if err != nil {
log.Printf("Unable to update info on upstream %s: %v", v.Name, err)
}
}
current := stratum.rpc()
poll(current)
// Async rpc call to not block on rpc timeout, ignoring current
go func() {
for _, v := range stratum.upstreams {
if v != current {
poll(v)
}
}
}()
infoTimer.Reset(infoIntv)
}
}
}()
return stratum return stratum
} }

22
www/index.html

@ -70,7 +70,7 @@
</div> </div>
<div class="col-xs-12"> <div class="col-xs-12">
<h4>Upstream</h4> <h4>Upstream</h4>
<table class="table table-condensed"> <table class="table table-condensed table-striped">
<tr> <tr>
<th>Name</th> <th>Name</th>
<th>Url</th> <th>Url</th>
@ -89,11 +89,21 @@
{{else}} {{else}}
<td>{{name}}</td> <td>{{name}}</td>
{{/if}} {{/if}}
<td>{{url}}</td> <td>{{url}}</td>
<td>{{formatNumber accepts}}</td> <td>{{formatNumber accepts}}</td>
<td><strong>{{formatNumber rejects}}</strong></td> <td><strong>{{formatNumber rejects}}</strong></td>
<td>{{failsCount}}</td> <td>{{failsCount}}</td>
</tr> {{#if info}}
<tr>
<td colspan="5" class="small">
<strong>Status:</strong> <span class="label label-default">{{info.status}}</span>
<strong>Height:</strong> <span class="label label-default">{{info.height}}</span>
<strong>Tx Pool Size:</strong> <span class="label label-default">{{info.tx_pool_size}}</span>
<strong>In:</strong> <span class="label label-default">{{info.incoming_connections_count}}</span>
<strong>Out:</strong> <span class="label label-default">{{info.outgoing_connections_count}}</span>
</td>
</tr>
{{/if}}
{{/each}} {{/each}}
</table> </table>
</div> </div>

Loading…
Cancel
Save