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)
	}
}
Exemple #2
0
// 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
}