192 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package bolt
 | |
| 
 | |
| import (
 | |
| 	"encoding/binary"
 | |
| 	"git.binarythought.com/cdramey/qurl/obj"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	QURLBucket    = []byte{0x00}
 | |
| 	ReverseBucket = []byte{0x01}
 | |
| 
 | |
| 	URLField     = []byte{0x00}
 | |
| 	CreatedField = []byte{0x01}
 | |
| 	IPField      = []byte{0x02}
 | |
| 	BrowserField = []byte{0x03}
 | |
| )
 | |
| 
 | |
| func (stor *BoltStorage) AddQURL(q *obj.QURL) error {
 | |
| 	tx, err := stor.DB.Begin(true)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	defer tx.Rollback()
 | |
| 
 | |
| 	rb, err := tx.CreateBucketIfNotExists(QURLBucket)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	// Populate the ID from the sequence if we don't have one
 | |
| 	if q.ID == 0 {
 | |
| 		s, err := rb.NextSequence()
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		// Bolt's sequence starts at 1, so for
 | |
| 		// backwards compatibility we have subtract
 | |
| 		// one so we're zero-based
 | |
| 		q.ID = (s - 1)
 | |
| 	}
 | |
| 
 | |
| 	// Create a byte array from the ID
 | |
| 	bid := make([]byte, 8)
 | |
| 	binary.BigEndian.PutUint64(bid, q.ID)
 | |
| 
 | |
| 	// Add an entry into the reverse indexed bucket for quickly
 | |
| 	// determining if a URL is already in the database
 | |
| 	ab, err := tx.CreateBucketIfNotExists(ReverseBucket)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	err = ab.Put([]byte(q.URL), bid)
 | |
| 
 | |
| 	qb, err := rb.CreateBucketIfNotExists(bid)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	// Write the ID to URL
 | |
| 	err = qb.Put(URLField, []byte(q.URL))
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	if !q.Created.IsZero() {
 | |
| 		// Create byte array from the Created date
 | |
| 		bdt, err := q.Created.MarshalBinary()
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		// Write the Created date
 | |
| 		err = qb.Put(CreatedField, bdt)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if q.IP != nil {
 | |
| 		err = qb.Put(IPField, q.IP)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if len(q.Browser) > 0 {
 | |
| 		err = qb.Put(BrowserField, []byte(q.Browser))
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if err := tx.Commit(); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (stor *BoltStorage) SetQURLSequence(seq uint64) error {
 | |
| 	tx, err := stor.DB.Begin(true)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	defer tx.Rollback()
 | |
| 
 | |
| 	qb, err := tx.CreateBucketIfNotExists(QURLBucket)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	// Since the sequence number is decremented by one
 | |
| 	// for backwards compatibility (see above)
 | |
| 	// we increment it by one when setting the sequence
 | |
| 	qb.SetSequence(seq + 1)
 | |
| 
 | |
| 	if err := tx.Commit(); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (stor *BoltStorage) GetQURLByURL(u string) (*obj.QURL, error) {
 | |
| 	tx, err := stor.DB.Begin(false)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	defer tx.Rollback()
 | |
| 
 | |
| 	ab := tx.Bucket(ReverseBucket)
 | |
| 	if ab == nil {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 
 | |
| 	bid := ab.Get([]byte(u))
 | |
| 	if bid == nil {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 
 | |
| 	rb := tx.Bucket(QURLBucket)
 | |
| 	if rb == nil {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 
 | |
| 	qb := rb.Bucket(bid)
 | |
| 	if qb == nil {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 
 | |
| 	q := &obj.QURL{ID: binary.BigEndian.Uint64(bid)}
 | |
| 
 | |
| 	qu := qb.Get(URLField)
 | |
| 	if qu != nil {
 | |
| 		q.URL = string(qu)
 | |
| 	}
 | |
| 
 | |
| 	return q, nil
 | |
| }
 | |
| 
 | |
| func (stor *BoltStorage) GetQURLByID(id uint64) (*obj.QURL, error) {
 | |
| 	tx, err := stor.DB.Begin(false)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	defer tx.Rollback()
 | |
| 
 | |
| 	// Create a byte array from the ID
 | |
| 	bid := make([]byte, 8)
 | |
| 	binary.BigEndian.PutUint64(bid, id)
 | |
| 
 | |
| 	rb := tx.Bucket(QURLBucket)
 | |
| 	if rb == nil {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 
 | |
| 	qb := rb.Bucket(bid)
 | |
| 	if qb == nil {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 
 | |
| 	q := &obj.QURL{ID: id}
 | |
| 
 | |
| 	qu := qb.Get(URLField)
 | |
| 	if qu != nil {
 | |
| 		q.URL = string(qu)
 | |
| 	}
 | |
| 
 | |
| 	return q, nil
 | |
| }
 |