a simple url shortener in Go (check it out at qurl.org)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
3.1 KiB

6 years ago
  1. package bolt
  2. import (
  3. "encoding/binary"
  4. "qurl/qurl"
  5. // "bytes"
  6. // "fmt"
  7. )
  8. var (
  9. QURLBucket = []byte{0x00}
  10. ReverseBucket = []byte{0x01}
  11. URLField = []byte{0x00}
  12. CreatedField = []byte{0x01}
  13. IPField = []byte{0x02}
  14. BrowserField = []byte{0x03}
  15. )
  16. func (stor *BoltStorage) AddQURL(qurl *qurl.QURL) error {
  17. tx, err := stor.DB.Begin(true)
  18. if err != nil {
  19. return err
  20. }
  21. defer tx.Rollback()
  22. rb, err := tx.CreateBucketIfNotExists(QURLBucket)
  23. if err != nil {
  24. return err
  25. }
  26. // Populate the ID from the sequence if we don't have one
  27. if qurl.ID == 0 {
  28. qurl.ID, err = rb.NextSequence()
  29. if err != nil {
  30. return err
  31. }
  32. }
  33. // Create a byte array from the ID
  34. bid := make([]byte, 8)
  35. binary.BigEndian.PutUint64(bid, qurl.ID)
  36. // Add an entry into the reverse indexed bucket for quickly
  37. // determining if a URL is already in the database
  38. ab, err := tx.CreateBucketIfNotExists(ReverseBucket)
  39. if err != nil {
  40. return err
  41. }
  42. err = ab.Put([]byte(qurl.URL), bid)
  43. qb, err := rb.CreateBucketIfNotExists(bid)
  44. if err != nil {
  45. return err
  46. }
  47. // Write the ID to URL
  48. err = qb.Put(URLField, []byte(qurl.URL))
  49. if err != nil {
  50. return err
  51. }
  52. if !qurl.Created.IsZero() {
  53. // Create byte array from the Created date
  54. bdt, err := qurl.Created.MarshalBinary()
  55. if err != nil {
  56. return err
  57. }
  58. // Write the Created date
  59. err = qb.Put(CreatedField, bdt)
  60. if err != nil {
  61. return err
  62. }
  63. }
  64. if qurl.IP != nil {
  65. err = qb.Put(IPField, qurl.IP)
  66. if err != nil {
  67. return err
  68. }
  69. }
  70. if len(qurl.Browser) > 0 {
  71. err = qb.Put(BrowserField, []byte(qurl.Browser))
  72. if err != nil {
  73. return err
  74. }
  75. }
  76. if err := tx.Commit(); err != nil {
  77. return err
  78. }
  79. return nil
  80. }
  81. func (stor *BoltStorage) SetQURLSequence(seq uint64) error {
  82. tx, err := stor.DB.Begin(true)
  83. if err != nil {
  84. return err
  85. }
  86. defer tx.Rollback()
  87. qb, err := tx.CreateBucketIfNotExists(QURLBucket)
  88. if err != nil {
  89. return err
  90. }
  91. qb.SetSequence(seq)
  92. if err := tx.Commit(); err != nil {
  93. return err
  94. }
  95. return nil
  96. }
  97. func (stor *BoltStorage) GetQURLByURL(u string) (*qurl.QURL, error) {
  98. tx, err := stor.DB.Begin(false)
  99. if err != nil {
  100. return nil, err
  101. }
  102. defer tx.Rollback()
  103. ab := tx.Bucket(ReverseBucket)
  104. if ab == nil {
  105. return nil, nil
  106. }
  107. bid := ab.Get([]byte(u))
  108. if bid == nil {
  109. return nil, nil
  110. }
  111. rb := tx.Bucket(QURLBucket)
  112. if rb == nil {
  113. return nil, nil
  114. }
  115. qb := rb.Bucket(bid)
  116. if qb == nil {
  117. return nil, nil
  118. }
  119. qurl := &qurl.QURL{ ID: binary.BigEndian.Uint64(bid) }
  120. qu := qb.Get(URLField)
  121. if qu != nil {
  122. qurl.URL = string(qu)
  123. }
  124. return qurl, nil
  125. }
  126. /*
  127. func (stor *BoltStorage) GetQURLByURL(u string) (*qurl.QURL, error) {
  128. tx, err := stor.DB.Begin(false)
  129. if err != nil {
  130. return nil, err
  131. }
  132. defer tx.Rollback()
  133. rb := tx.Bucket(QURLBucket)
  134. if rb == nil {
  135. return nil, nil
  136. }
  137. bu := []byte(u)
  138. rc := rb.Cursor()
  139. for k, _ := rc.First(); k != nil; k, _ = rc.Next() {
  140. qb := rb.Bucket(k)
  141. if qb == nil {
  142. continue
  143. }
  144. qu := qb.Get(URLField)
  145. if bytes.Equal(bu, qu) {
  146. qurl := &qurl.QURL{
  147. ID: binary.BigEndian.Uint64(k),
  148. URL: string(qu),
  149. }
  150. return qurl, nil
  151. }
  152. }
  153. return nil, nil
  154. }
  155. */