// expireUnreachableNodes is invoked once per day to finally delete nodes which // have been offline for too long. The default interval is one year. // All information in all buckets regarding the expired nodes is removed. func (bs *BoltStore) expireUnreachableNodes() { now := time.Now() expireDuration := time.Duration(conf.UInt("store.expireNodesAfterDays", 365)*24) * time.Hour expireSeconds := expireDuration.Seconds() expiredNodeIds := make([]string, 0, 50) err := bs.db.Update(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(StatusInfoBucket)) nodeinfoBucket := tx.Bucket([]byte(NodeinfoBucket)) statsBucket := tx.Bucket([]byte(StatisticsBucket)) neighbourBucket := tx.Bucket([]byte(NeighboursBucket)) gatewayBucket := tx.Bucket([]byte(GatewayBucket)) c := b.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { status := NodeStatusInfo{} err := json.Unmarshal(v, &status) if err != nil { log.WithFields(log.Fields{ "error": err, "nodeId": k, "jsonString": string(v), }).Error("Can't unmarshall json from node status info") continue } var lastseen time.Time lastseen, err = time.Parse(TimeFormat, status.Lastseen) if err != nil { // In case we have imported data from ffmap-backend still in our database lastseen, err = time.Parse(LegacyTimeFormat, status.Lastseen) if err != nil { log.WithFields(log.Fields{ "error": err, "timeString": status.Lastseen, "nodeId": status.NodeId, }).Error("Can't parse lastseen time") } } if (now.Unix() - lastseen.Unix()) > int64(expireSeconds) { log.WithFields(log.Fields{ "nodeid": string(k), "lastseen": status.Lastseen, }).Info("Deleting node as it is considered gone forever after") b.Delete(k) nodeinfoBucket.Delete(k) statsBucket.Delete(k) neighbourBucket.Delete(k) gatewayBucket.Delete(k) expiredNodeIds = append(expiredNodeIds, string(k)) } } return nil }) executeHandlersOnNodeIdList(expiredNodeIds, bs.expiredNodesHandler) if err != nil { log.WithFields(log.Fields{ "error": err, }).Error("Error in database transaction while updating online status") } }
func (s *SimpleInMemoryStore) PutStatistics(statistics StatisticsStruct) { s.statistics.Add(statistics.NodeId, time.Second*time.Duration(conf.UInt("announced.interval.statistics", 300)*2), &statistics) //s.Statistics[statistics.NodeId] = &statistics }
// calculateOnlineStatus is invoked once a minute to calculate the current // online status of a node. A node is considered to be offline if it has missed // to report data back on multiple requests. Eventually the node is tried via // unicast, which could bring her back. func (bs *BoltStore) calculateOnlineStatus() { now := time.Now() updateInterval := conf.UInt("announced.interval.statistics", 300) factor := conf.UInt("announced.interval.expire", 3) offlineInterval := updateInterval * factor offlineNodeIds := make([]string, 0, 50) err := bs.db.Update(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(StatusInfoBucket)) c := b.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { status := NodeStatusInfo{} err := json.Unmarshal(v, &status) if err != nil { log.WithFields(log.Fields{ "error": err, "nodeId": k, "jsonString": string(v), }).Error("Can't unmarshall json from node status info") continue } var lastseen time.Time lastseen, err = time.Parse(TimeFormat, status.Lastseen) if err != nil { // In case we have imported data from ffmap-backend still in our database lastseen, err = time.Parse(LegacyTimeFormat, status.Lastseen) if err != nil { log.WithFields(log.Fields{ "error": err, "timeString": status.Lastseen, "nodeId": status.NodeId, }).Error("Can't parse lastseen time") } } if (now.Unix()-lastseen.Unix()) > int64(offlineInterval) && status.Online { log.WithFields(log.Fields{ "nodeid": string(k), "lastseen": status.Lastseen, }).Info("Node is considered offline after being unreachable for too long") status.Online = false offlineNodeIds = append(offlineNodeIds, string(k)) if status.NodeId == "" { status.NodeId = string(k) } data, err := json.Marshal(status) if err == nil { b.Put(k, data) } else { log.WithFields(log.Fields{ "error": err, "nodeStatus": status, "nodeid": string(k), }).Error("Can't marshall node status info") } } } return nil }) executeHandlersOnNodeIdList(offlineNodeIds, bs.gwOfflineHandler) if err != nil { log.WithFields(log.Fields{ "error": err, }).Error("Error in database transaction while updating online status") } }
func (s *SimpleInMemoryStore) PutNodeNeighbours(neighbours NeighbourStruct) { s.neighbourCache.Add(neighbours.NodeId, time.Second*time.Duration(conf.UInt("announced.interval.statistics", 300)*2), &neighbours) //s.NeighbourInfos[neighbours.NodeId] = &neighbours }