diff --git a/main.go b/main.go index 68a4e3227..4eeb4c366 100644 --- a/main.go +++ b/main.go @@ -18,6 +18,7 @@ package main import ( "fmt" + "io/ioutil" "os" "os/user" "path" @@ -264,6 +265,8 @@ func main() { globalDebugFlag = c.GlobalBool("debug") if globalDebugFlag { app.ExtraInfo = getSystemData() + } else { + log.Debug = log.New(ioutil.Discard, "", 0) } return nil } diff --git a/pkg/api/quota/bandwidth_cap.go b/pkg/api/quota/bandwidth_cap.go index b4e8f3230..47c7bc4a3 100644 --- a/pkg/api/quota/bandwidth_cap.go +++ b/pkg/api/quota/bandwidth_cap.go @@ -23,9 +23,10 @@ import ( "net/http" "time" + "sync" + "github.com/minio-io/minio/pkg/iodine" "github.com/minio-io/minio/pkg/utils/log" - "sync" ) // bandwidthQuotaHandler @@ -39,6 +40,8 @@ func (h *bandwidthQuotaHandler) ServeHTTP(w http.ResponseWriter, req *http.Reque host, _, _ := net.SplitHostPort(req.RemoteAddr) longIP := longIP{net.ParseIP(host)}.IptoUint32() if h.quotas.WillExceedQuota(longIP, req.ContentLength) { + hosts, _ := net.LookupAddr(uint32ToIP(longIP).String()) + log.Debug.Printf("Offending Host: %s, BandwidthUsed: %d", hosts, h.quotas.GetQuotaUsed(longIP)) writeErrorResponse(w, req, BandWidthInsufficientToProceed, req.URL.Path) return } @@ -94,6 +97,8 @@ func (q *quotaReader) Read(b []byte) (int, error) { if q.err == false && q.quotas.IsQuotaMet(q.ip) { defer q.lock.Unlock() q.err = true + hosts, _ := net.LookupAddr(uint32ToIP(q.ip).String()) + log.Debug.Printf("Offending Host: %s, BandwidthUsed: %d", hosts, q.quotas.GetQuotaUsed(q.ip)) writeErrorResponse(q.w, q.req, BandWidthQuotaExceeded, q.req.URL.Path) return 0, iodine.New(errors.New("Quota Met"), nil) } diff --git a/pkg/api/quota/quota_handler.go b/pkg/api/quota/quota_handler.go index 461d3d919..d4ecfc0b9 100644 --- a/pkg/api/quota/quota_handler.go +++ b/pkg/api/quota/quota_handler.go @@ -32,10 +32,21 @@ type quotaMap struct { segmentSize time.Duration } +func (q *quotaMap) CanExpire() { + currentMinute := time.Now().UnixNano() / q.segmentSize.Nanoseconds() + // divide by segmentSize, otherwise expiredQuotas will always be negative + expiredQuotas := currentMinute - (q.duration.Nanoseconds() / q.segmentSize.Nanoseconds()) + for time := range q.data { + if time < expiredQuotas { + delete(q.data, time) + } + } +} + func (q *quotaMap) Add(ip uint32, size int64) { q.Lock() defer q.Unlock() - q.clean() + q.CanExpire() currentMinute := time.Now().UnixNano() / q.segmentSize.Nanoseconds() if _, ok := q.data[currentMinute]; !ok { q.data[currentMinute] = make(map[uint32]int64) @@ -46,7 +57,7 @@ func (q *quotaMap) Add(ip uint32, size int64) { } func (q *quotaMap) IsQuotaMet(ip uint32) bool { - q.clean() + q.CanExpire() if q.GetQuotaUsed(ip) >= q.limit { return true } @@ -70,16 +81,6 @@ func (q *quotaMap) WillExceedQuota(ip uint32, size int64) (result bool) { return q.GetQuotaUsed(ip)+size > q.limit } -func (q *quotaMap) clean() { - currentMinute := time.Now().UnixNano() / q.segmentSize.Nanoseconds() - expiredQuotas := currentMinute - q.duration.Nanoseconds() - for time := range q.data { - if time < expiredQuotas { - delete(q.data, time) - } - } -} - type longIP struct { net.IP } diff --git a/pkg/api/quota/request_limit.go b/pkg/api/quota/request_limit.go index d85c593e8..85413a37a 100644 --- a/pkg/api/quota/request_limit.go +++ b/pkg/api/quota/request_limit.go @@ -17,9 +17,12 @@ package quota import ( + "encoding/binary" "net" "net/http" "time" + + "github.com/minio-io/minio/pkg/utils/log" ) // requestLimitHandler @@ -28,11 +31,20 @@ type requestLimitHandler struct { quotas *quotaMap } +//convert a uint32 to an ipv4 +func uint32ToIP(ip uint32) net.IP { + addr := net.IP{0, 0, 0, 0} + binary.BigEndian.PutUint32(addr, ip) + return addr +} + // ServeHTTP is an http.Handler ServeHTTP method func (h *requestLimitHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { host, _, _ := net.SplitHostPort(req.RemoteAddr) longIP := longIP{net.ParseIP(host)}.IptoUint32() if h.quotas.IsQuotaMet(longIP) { + hosts, _ := net.LookupAddr(uint32ToIP(longIP).String()) + log.Debug.Printf("Offending Host: %s, RequestUSED: %d\n", hosts, h.quotas.GetQuotaUsed(longIP)) writeErrorResponse(w, req, SlowDown, req.URL.Path) } h.quotas.Add(longIP, 1)