github.com/orofarne/hammy@v0.0.0-20130409105742-374fadfd6ecb/src/hammy/couchbase_datareader.go (about) 1 package hammy 2 3 import ( 4 "fmt" 5 "sort" 6 "bytes" 7 "github.com/couchbaselabs/go-couchbase" 8 "github.com/ugorji/go-msgpack" 9 "github.com/dustin/gomemcached" 10 ) 11 12 // Reads data from write cache (couchbase-based) 13 type CouchbaseDataReader struct { 14 client *couchbase.Client 15 pool *couchbase.Pool 16 bucket *couchbase.Bucket 17 } 18 19 // Create new saver 20 func NewCouchbaseDataReader(cfg Config) (*CouchbaseDataReader, error) { 21 s := new(CouchbaseDataReader) 22 23 c, err := couchbase.Connect(cfg.CouchbaseDataReader.ConnectTo) 24 if err != nil { 25 return nil, err 26 } 27 s.client = &c 28 29 p, err := s.client.GetPool(cfg.CouchbaseDataReader.Pool) 30 if err != nil { 31 return nil, err 32 } 33 s.pool = &p 34 35 b, err := s.pool.GetBucket(cfg.CouchbaseDataReader.Bucket) 36 if err != nil { 37 return nil, err 38 } 39 s.bucket = b 40 41 return s, nil 42 } 43 44 func (cr *CouchbaseDataReader) Read(hostKey string, itemKey string, from uint64, to uint64) (data []IncomingValueData, err error) { 45 // Construct keys slice 46 bucketFrom, bucketTo := (from / CouchbaseDataBucketQuantum), (to / CouchbaseDataBucketQuantum) 47 keys := make([]string, (bucketTo - bucketFrom + 1)) 48 for i, k := 0, bucketFrom; k <= bucketTo; k++ { 49 keys[i] = fmt.Sprintf("%s$%s$%d", hostKey, itemKey, k) 50 i++ 51 } 52 53 // Retrive data 54 ans := cr.bucket.GetBulk(keys) 55 dataLen := 0 56 57 for _, r := range ans { 58 switch r.Status { 59 case gomemcached.SUCCESS: 60 dataLen += len(r.Body) 61 case gomemcached.KEY_ENOENT: 62 // nil 63 default: 64 err = fmt.Errorf("GetBult error: %s", r.Error()) 65 return 66 } 67 } 68 69 if dataLen == 0 { 70 data = make([]IncomingValueData, 0) 71 return 72 } 73 74 dataRaw := make([]byte, dataLen) 75 j := 0 76 for _, r := range ans { 77 if r.Status == gomemcached.SUCCESS { 78 for i := 0; i < len(r.Body); i++ { 79 dataRaw[j] = r.Body[i] 80 j++ 81 if j > dataLen { 82 panic("Invalid j") 83 } 84 } 85 } 86 } 87 88 data = make([]IncomingValueData, 0) 89 dataRawBuffer := bytes.NewBuffer(dataRaw) 90 dec := msgpack.NewDecoder(dataRawBuffer, nil) 91 for { 92 var val IncomingValueData 93 err = dec.Decode(&val) 94 if err != nil { 95 if err.Error() == "EOF" { 96 err = nil 97 break 98 } else { 99 //err = fmt.Errorf("Unmarshal error: %#v (data: %#v)", err, dataRaw) 100 err = fmt.Errorf("Unmarshal error: %v", err) 101 return 102 } 103 } 104 105 data = append(data, val) 106 } 107 108 ds := DataTimeSorter{ 109 Data: &data, 110 } 111 sort.Sort(&ds) 112 113 // TODO: remove "bad" values 114 115 return 116 }