strategies.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package strategy
  2. import (
  3. "bytes"
  4. "database/sql"
  5. "fmt"
  6. "code.osinet.fr/fgm/kurz/storage"
  7. "log"
  8. )
  9. // StrategyMap adds helper methods to a map of AliasingStrategy
  10. type StrategyMap map[string]AliasingStrategy
  11. // IsValid() checks whether a strategy is registered for a given name.
  12. func (m StrategyMap) IsValid(name string) bool {
  13. var ok bool
  14. _, ok = m[name]
  15. return ok
  16. }
  17. // Strategies is a global instance of the registered strategies.
  18. var Strategies StrategyMap
  19. func MakeStrategies(list []AliasingStrategy) StrategyMap {
  20. ret := make(map[string]AliasingStrategy, len(list))
  21. for _, s := range list {
  22. ret[s.Name()] = s
  23. }
  24. return ret
  25. }
  26. // StatisticsMap adds helper methods to a map of AliasingStrategy use counts.
  27. type StatisticsMap map[string]int64
  28. // Statistics is a global instance of the AliasingStrategy use counts.
  29. var Statistics StatisticsMap
  30. // Get() fetches the AliasingStrategy use counts from the database and returns the updated Statistics.
  31. func (ss StatisticsMap) Refresh(s storage.Storage) StatisticsMap {
  32. var err error
  33. var strategyResult sql.NullString
  34. var countResult sql.NullInt64
  35. sql := `
  36. SELECT strategy, COUNT(*)
  37. FROM shorturl
  38. GROUP BY strategy
  39. `
  40. rows, err := s.DB.Query(sql)
  41. if err != nil {
  42. log.Printf("Failed querying database for strategy statistics: %v\n", err)
  43. }
  44. defer rows.Close()
  45. for rows.Next() {
  46. if err = rows.Scan(&strategyResult, &countResult); err != nil {
  47. log.Fatal(err)
  48. }
  49. if !Strategies.IsValid(strategyResult.String) {
  50. log.Fatalf("'%#v' is not a valid strategy\n", strategyResult)
  51. }
  52. ss[strategyResult.String] = countResult.Int64
  53. }
  54. for name, _ := range Strategies {
  55. _, ok := ss[name]
  56. if !ok {
  57. ss[name] = 0
  58. }
  59. }
  60. return ss
  61. }
  62. // String() implements the fmt.Stringer interface.
  63. func (ss StatisticsMap) String() string {
  64. var buf bytes.Buffer
  65. for name, count := range ss {
  66. buf.WriteString(fmt.Sprintf("%-8s: %d\n", name, count))
  67. }
  68. return fmt.Sprint(buf.String())
  69. }
  70. // init() initializes the global variables provided by the package.
  71. func init() {
  72. Strategies = MakeStrategies([]AliasingStrategy{
  73. baseStrategy{},
  74. HexCrc32Strategy{},
  75. ManualStrategy{},
  76. })
  77. Statistics = make(map[string]int64, len(Strategies))
  78. }