Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

store multiple values in maps

Tags:

go

maps

problem: Store both an IP address as well as a time to a counter. something like this

ip, time, count

and then i would like to be able to increment the count for each ip:

ip++

in my map, and then on a given interval, i would like to iterate all keys and find the keys with a time stamp older than N minutes.

I need this to make sure i don't "forget" a key in memory if for some reason, client disconnect and i dont delete the key properly.

http://play.golang.org/p/RiWWOCARq7

Question: How do i add a time stamp to every IP address i store in my map. Also i need this be be used across multiple go routines

Im new to both programming and Golang, so if this is not even the correct approach, if anyone could point me in the right direction, i would appreciate it.

like image 890
Ventosus Avatar asked Dec 03 '22 19:12

Ventosus


2 Answers

For example,

package main

import (
    "sync"
    "time"
)

type IPCounter struct {
    IPAddr string
    Time   time.Time
    Count  int
}

type ipCounterMap struct {
    counters map[string]IPCounter
    mutex    sync.RWMutex
}

var ipCounters = ipCounterMap{counters: make(map[string]IPCounter)}

// Get IP address counter
func Counter(ipAddr string) IPCounter {
    ipCounters.mutex.RLock()
    defer ipCounters.mutex.RUnlock()
    counter, found := ipCounters.counters[ipAddr]
    if !found {
        counter.IPAddr = ipAddr
    }
    return counter
}

// Increment IP address counter
func Incr(ipAddr string) {
    now := time.Now().UTC()
    ipCounters.mutex.Lock()
    defer ipCounters.mutex.Unlock()
    counter, found := ipCounters.counters[ipAddr]
    if !found {
        counter.IPAddr = ipAddr
    }
    counter.Time = now
    counter.Count++
    ipCounters.counters[ipAddr] = counter
}

// Delete IP address counter
func Delete(ipAddr string) {
    ipCounters.mutex.Lock()
    defer ipCounters.mutex.Unlock()
    delete(ipCounters.counters, ipAddr)
}

// Get old IP address counters old durations ago
func OldIPCounters(old time.Duration) []IPCounter {
    var counters []IPCounter
    oldTime := time.Now().UTC().Add(-old)
    ipCounters.mutex.RLock()
    defer ipCounters.mutex.RUnlock()
    for _, counter := range ipCounters.counters {
        if counter.Time.Before(oldTime) {
            counters = append(counters, counter)
        }
    }
    return counters
}

func main() {}
like image 57
peterSO Avatar answered Jan 14 '23 17:01

peterSO


You probably want a map of ip -> struct { ip, counter, lastTime } that way, you can look up the counter by ip and then update it

var Counters = map[string]*Counter{}

type Counter struct {
    ip       string
    count    int
    lastTime time.Time
}

Here's a working example on Play http://play.golang.org/p/TlCTc_4iq5

Adding the find older than is simply range over the values of the map comparing to now and do something when it's old enough.

like image 28
David Budworth Avatar answered Jan 14 '23 17:01

David Budworth