Example #1
0
// load loads a session data from the database.
// True is returned if there is a session data in the database.
func (s *Store) load(session *sessions.Session) (bool, error) {
	// exists represents whether a session data exists or not.
	var exists bool
	err := s.db.View(func(tx *bolt.Tx) error {
		id := []byte(session.ID)
		bucket := tx.Bucket(s.config.DBOptions.BucketName)
		// Get the session data.
		data := bucket.Get(id)
		if data == nil {
			return nil
		}
		sessionData, err := shared.Session(data)
		if err != nil {
			return err
		}
		// Check the expiration of the session data.
		if shared.Expired(sessionData) {
			err := s.db.Update(func(txu *bolt.Tx) error {
				return txu.Bucket(s.config.DBOptions.BucketName).Delete(id)
			})
			return err
		}
		exists = true
		dec := gob.NewDecoder(bytes.NewBuffer(sessionData.Values))
		return dec.Decode(&session.Values)
	})
	return exists, err
}
Example #2
0
func reap(db *bolt.DB, options Options, quitC <-chan struct{}, doneC chan<- struct{}) {
	var prevKey []byte
	for {
		err := db.View(func(tx *bolt.Tx) error {
			bucket := tx.Bucket(options.BucketName)
			if bucket == nil {
				return nil
			}

			c := bucket.Cursor()

			var i int

			for k, v := c.Seek(prevKey); ; k, v = c.Next() {
				// If we hit the end of our sessions then
				// exit and start over next time.
				if k == nil {
					prevKey = nil
					return nil
				}

				i++

				session, err := shared.Session(v)
				if err != nil {
					return err
				}

				if shared.Expired(session) {
					err := db.Update(func(txu *bolt.Tx) error {
						return txu.Bucket(options.BucketName).Delete(k)
					})
					if err != nil {
						return err
					}
				}

				if options.BatchSize == i {
					copy(prevKey, k)
					return nil
				}
			}
		})

		if err != nil {
			log.Println(err.Error())
		}

		// Check if a quit signal is sent.
		select {
		case <-quitC:
			doneC <- struct{}{}
			return
		default:
		}

		time.Sleep(options.CheckInterval)
	}
}
Example #3
0
func reap(db *bolt.DB, options Options, quitC <-chan struct{}, doneC chan<- struct{}) {
	// Create a new ticker
	ticker := time.NewTicker(options.CheckInterval)

	defer func() {
		// Stop the ticker
		ticker.Stop()
	}()

	var prevKey []byte

	for {
		select {
		case <-quitC: // Check if a quit signal is sent.
			doneC <- struct{}{}
			return
		case <-ticker.C: // Check if the ticker fires a signal.
			// This slice is a buffer to save all expired session keys.
			expiredSessionKeys := make([][]byte, 0)

			// Start a bolt read transaction.
			err := db.View(func(tx *bolt.Tx) error {
				bucket := tx.Bucket(options.BucketName)
				if bucket == nil {
					return nil
				}

				c := bucket.Cursor()

				var i int
				var isExpired bool

				for k, v := c.Seek(prevKey); ; k, v = c.Next() {
					// If we hit the end of our sessions then
					// exit and start over next time.
					if k == nil {
						prevKey = nil
						return nil
					}

					i++

					// The flag if the session is expired
					isExpired = false

					session, err := shared.Session(v)
					if err != nil {
						// Just remove the session with the invalid session data.
						// Log the error first.
						log.Printf("boltstore: removing session from database with invalid value: %v", err)
						isExpired = true
					} else if shared.Expired(session) {
						isExpired = true
					}

					if isExpired {
						// Copy the byte slice key, because this data is
						// not safe outside of this transaction.
						temp := make([]byte, len(k))
						copy(temp, k)

						// Add it to the expired sessios keys slice
						expiredSessionKeys = append(expiredSessionKeys, temp)
					}

					if options.BatchSize == i {
						// Store the current key to the previous key.
						// Copy the byte slice key, because this data is
						// not safe outside of this transaction.
						prevKey = make([]byte, len(k))
						copy(prevKey, k)
						return nil
					}
				}
			})

			if err != nil {
				log.Printf("boltstore: obtain expired sessions error: %v", err)
			}

			if len(expiredSessionKeys) > 0 {
				// Remove the expired sessions from the database
				err = db.Update(func(txu *bolt.Tx) error {
					// Get the bucket
					b := txu.Bucket(options.BucketName)
					if b == nil {
						return nil
					}

					// Remove all expired sessions in the slice
					for _, key := range expiredSessionKeys {
						err = b.Delete(key)
						if err != nil {
							return err
						}
					}

					return nil
				})

				if err != nil {
					log.Printf("boltstore: remove expired sessions error: %v", err)
				}
			}
		}
	}
}