func (self *ProductViewAPI) ServeHTTP(w http.ResponseWriter, req *http.Request) { var cp *cassandra.ColumnParent var pred *cassandra.SlicePredicate var res []*cassandra.ColumnOrSuperColumn var csc *cassandra.ColumnOrSuperColumn var ire *cassandra.InvalidRequestException var ue *cassandra.UnavailableException var te *cassandra.TimedOutException var prod Product var err error var uuidstr string = req.FormValue("id") var ts int64 = 0 var uuid UUID var rawdata []byte numRequests.Add(1) numAPIRequests.Add(1) // Check the user is in the reqeuested scope. if !self.authenticator.IsAuthenticatedScope(req, self.scope) { numDisallowedScope.Add(1) http.Error(w, "You are not in the right group to access this resource", http.StatusForbidden) return } if len(uuidstr) <= 0 { http.Error(w, "Requested UUID empty", http.StatusNotAcceptable) return } uuid, err = ParseUUID(uuidstr) if err != nil { http.Error(w, "Requested UUID invalid", http.StatusNotAcceptable) return } cp = cassandra.NewColumnParent() cp.ColumnFamily = "products" pred = cassandra.NewSlicePredicate() pred.ColumnNames = [][]byte{ []byte("name"), []byte("price"), []byte("vendor"), []byte("barcodes"), []byte("stock"), } res, ire, ue, te, err = self.client.GetSlice([]byte(uuid), cp, pred, cassandra.ConsistencyLevel_ONE) if ire != nil { log.Print("Invalid request: ", ire.Why) productViewErrors.Add(ire.Why, 1) return } if ue != nil { log.Print("Unavailable") productViewErrors.Add("unavailable", 1) return } if te != nil { log.Print("Request to database backend timed out") productViewErrors.Add("timeout", 1) return } if err != nil { log.Print("Generic error: ", err) productViewErrors.Add(err.Error(), 1) return } for _, csc = range res { var col = csc.Column var cname string if !csc.IsSetColumn() { continue } cname = string(col.Name) if col.IsSetTimestamp() && col.Timestamp > ts { ts = col.Timestamp } if cname == "name" { prod.Name = string(col.Value) } else if cname == "price" { var buf *bytes.Buffer = bytes.NewBuffer(col.Value) err = binary.Read(buf, binary.BigEndian, &prod.Price) if err != nil { log.Print("Row ", uuid.String(), " price is invalid") productViewErrors.Add("corrupted-price", 1) } } else if cname == "vendor" { prod.VendorId = UUID(col.Value).String() } else if cname == "barcodes" { var bc Barcodes err = proto.Unmarshal(col.Value, &bc) if err != nil { log.Print("Row ", uuid.String(), " barcode is invalid") productViewErrors.Add("corrupted-barcode", 1) return } for _, code := range bc.Barcode { prod.Barcodes = append(prod.Barcodes, code) } } else if cname == "stock" { var buf *bytes.Buffer = bytes.NewBuffer(col.Value) err = binary.Read(buf, binary.BigEndian, &prod.Stock) if err != nil { log.Print("Row ", uuid.String(), " stock is invalid") productViewErrors.Add("corrupted-stock", 1) } } } rawdata, err = json.Marshal(prod) if err != nil { log.Print("Error marshalling JSON: ", err) numJSONMarshalErrors.Add(1) http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Add("Content-type", "application/json") w.WriteHeader(http.StatusOK) _, err = w.Write(rawdata) if err != nil { log.Print("Error writing JSON response: ", err) numHTTPWriteErrors.Add(err.Error(), 1) } }
// Move a member record to the queue for getting their user account removed // (e.g. when they leave us). Set the retention to 2 years instead of just // 6 months, since they have been a member. func (m *MembershipDB) MoveMemberToTrash(id, initiator, reason string) error { var now time.Time = time.Now() var now_long uint64 = uint64(now.Unix()) var uuid cassandra.UUID var mmap map[string]map[string][]*cassandra.Mutation var member *MembershipAgreement var cp *cassandra.ColumnPath = cassandra.NewColumnPath() var cos *cassandra.ColumnOrSuperColumn var del *cassandra.Deletion = cassandra.NewDeletion() var mu *cassandra.Mutation var ts int64 var err error cp.ColumnFamily = "members" cp.Column = []byte("pb_data") uuid, err = cassandra.GenTimeUUID(&now) if err != nil { return err } cos, err = m.conn.Get( []byte(memberPrefix+id), cp, cassandra.ConsistencyLevel_QUORUM) if err != nil { return err } member = new(MembershipAgreement) err = proto.Unmarshal(cos.Column.Value, member) if err != nil { return err } del.Predicate = cassandra.NewSlicePredicate() del.Predicate.ColumnNames = allColumns del.Timestamp = cos.Column.Timestamp mu = cassandra.NewMutation() mu.Deletion = del mmap = make(map[string]map[string][]*cassandra.Mutation) mmap[memberPrefix+id] = make(map[string][]*cassandra.Mutation) mmap[memberPrefix+id]["members"] = []*cassandra.Mutation{mu} member.Metadata.GoodbyeInitiator = &initiator member.Metadata.GoodbyeTimestamp = &now_long member.Metadata.GoodbyeReason = &reason ts = now.UnixNano() cos.Column = cassandra.NewColumn() cos.Column.Name = []byte("pb_data") cos.Column.Timestamp = &ts cos.Column.Value, err = proto.Marshal(member) if err != nil { return err } mu = cassandra.NewMutation() mu.ColumnOrSupercolumn = cos mmap[dequeuePrefix+id] = make(map[string][]*cassandra.Mutation) mmap[dequeuePrefix+string([]byte(uuid))] = make(map[string][]*cassandra.Mutation) mmap[dequeuePrefix+string([]byte(uuid))]["membership_dequeue"] = []*cassandra.Mutation{mu} err = m.conn.AtomicBatchMutate( mmap, cassandra.ConsistencyLevel_QUORUM) return err }