mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-13 11:11:30 -04:00
Added another lock to protect broker stats
Added another lock to the metrics struct to synchronize accesses to the broker stats. There's a possible race condition if stats are updated at the same time they are being logged.
This commit is contained in:
parent
42e16021c4
commit
06298eec73
2 changed files with 14 additions and 1 deletions
|
@ -38,7 +38,7 @@ type BrokerContext struct {
|
||||||
// Map keeping track of snowflakeIDs required to match SDP answers from
|
// Map keeping track of snowflakeIDs required to match SDP answers from
|
||||||
// the second http POST.
|
// the second http POST.
|
||||||
idToSnowflake map[string]*Snowflake
|
idToSnowflake map[string]*Snowflake
|
||||||
// Synchronization for the
|
// Synchronization for the snowflake map and heap
|
||||||
snowflakeLock sync.Mutex
|
snowflakeLock sync.Mutex
|
||||||
proxyPolls chan *ProxyPoll
|
proxyPolls chan *ProxyPoll
|
||||||
metrics *Metrics
|
metrics *Metrics
|
||||||
|
@ -181,14 +181,18 @@ func proxyPolls(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error processing proxy IP: ", err.Error())
|
log.Println("Error processing proxy IP: ", err.Error())
|
||||||
} else {
|
} else {
|
||||||
|
ctx.metrics.lock.Lock()
|
||||||
ctx.metrics.UpdateCountryStats(remoteIP, proxyType)
|
ctx.metrics.UpdateCountryStats(remoteIP, proxyType)
|
||||||
|
ctx.metrics.lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for a client to avail an offer to the snowflake, or timeout if nil.
|
// Wait for a client to avail an offer to the snowflake, or timeout if nil.
|
||||||
offer := ctx.RequestOffer(sid, proxyType)
|
offer := ctx.RequestOffer(sid, proxyType)
|
||||||
var b []byte
|
var b []byte
|
||||||
if nil == offer {
|
if nil == offer {
|
||||||
|
ctx.metrics.lock.Lock()
|
||||||
ctx.metrics.proxyIdleCount++
|
ctx.metrics.proxyIdleCount++
|
||||||
|
ctx.metrics.lock.Unlock()
|
||||||
|
|
||||||
b, err = messages.EncodePollResponse("", false)
|
b, err = messages.EncodePollResponse("", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -227,7 +231,9 @@ func clientOffers(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
|
||||||
numSnowflakes := ctx.snowflakes.Len()
|
numSnowflakes := ctx.snowflakes.Len()
|
||||||
ctx.snowflakeLock.Unlock()
|
ctx.snowflakeLock.Unlock()
|
||||||
if numSnowflakes <= 0 {
|
if numSnowflakes <= 0 {
|
||||||
|
ctx.metrics.lock.Lock()
|
||||||
ctx.metrics.clientDeniedCount++
|
ctx.metrics.clientDeniedCount++
|
||||||
|
ctx.metrics.lock.Unlock()
|
||||||
w.WriteHeader(http.StatusServiceUnavailable)
|
w.WriteHeader(http.StatusServiceUnavailable)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -241,7 +247,9 @@ func clientOffers(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
|
||||||
// Wait for the answer to be returned on the channel or timeout.
|
// Wait for the answer to be returned on the channel or timeout.
|
||||||
select {
|
select {
|
||||||
case answer := <-snowflake.answerChannel:
|
case answer := <-snowflake.answerChannel:
|
||||||
|
ctx.metrics.lock.Lock()
|
||||||
ctx.metrics.clientProxyMatchCount++
|
ctx.metrics.clientProxyMatchCount++
|
||||||
|
ctx.metrics.lock.Unlock()
|
||||||
if _, err := w.Write(answer); err != nil {
|
if _, err := w.Write(answer); err != nil {
|
||||||
log.Printf("unable to write answer with error: %v", err)
|
log.Printf("unable to write answer with error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,9 @@ type Metrics struct {
|
||||||
proxyIdleCount uint
|
proxyIdleCount uint
|
||||||
clientDeniedCount uint
|
clientDeniedCount uint
|
||||||
clientProxyMatchCount uint
|
clientProxyMatchCount uint
|
||||||
|
|
||||||
|
//synchronization for access to snowflake metrics
|
||||||
|
lock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s CountryStats) Display() string {
|
func (s CountryStats) Display() string {
|
||||||
|
@ -161,6 +164,7 @@ func (m *Metrics) logMetrics() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Metrics) printMetrics() {
|
func (m *Metrics) printMetrics() {
|
||||||
|
m.lock.Lock()
|
||||||
m.logger.Println("snowflake-stats-end", time.Now().UTC().Format("2006-01-02 15:04:05"), fmt.Sprintf("(%d s)", int(metricsResolution.Seconds())))
|
m.logger.Println("snowflake-stats-end", time.Now().UTC().Format("2006-01-02 15:04:05"), fmt.Sprintf("(%d s)", int(metricsResolution.Seconds())))
|
||||||
m.logger.Println("snowflake-ips", m.countryStats.Display())
|
m.logger.Println("snowflake-ips", m.countryStats.Display())
|
||||||
m.logger.Println("snowflake-ips-total", len(m.countryStats.standalone)+
|
m.logger.Println("snowflake-ips-total", len(m.countryStats.standalone)+
|
||||||
|
@ -171,6 +175,7 @@ func (m *Metrics) printMetrics() {
|
||||||
m.logger.Println("snowflake-idle-count", binCount(m.proxyIdleCount))
|
m.logger.Println("snowflake-idle-count", binCount(m.proxyIdleCount))
|
||||||
m.logger.Println("client-denied-count", binCount(m.clientDeniedCount))
|
m.logger.Println("client-denied-count", binCount(m.clientDeniedCount))
|
||||||
m.logger.Println("client-snowflake-match-count", binCount(m.clientProxyMatchCount))
|
m.logger.Println("client-snowflake-match-count", binCount(m.clientProxyMatchCount))
|
||||||
|
m.lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restores all metrics to original values
|
// Restores all metrics to original values
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue