Skip to content
Snippets Groups Projects
Commit 06298eec authored by Cecylia Bocovich's avatar Cecylia Bocovich :speech_balloon:
Browse files

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.
parent 42e16021
Branches
Tags
No related merge requests found
...@@ -38,7 +38,7 @@ type BrokerContext struct { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 { ...@@ -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() { ...@@ -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() { ...@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment