예제 #1
0
// 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")
	}
}
예제 #2
0
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
}
예제 #3
0
// 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")
	}
}
예제 #4
0
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
}