Example #1
0
func (t *txnBufState) fixKeys(keys []*datastore.Key) ([]*datastore.Key, error) {
	lme := errors.NewLazyMultiError(len(keys))
	realKeys := []*datastore.Key(nil)
	for i, key := range keys {
		if key.Incomplete() {
			// intentionally call AllocateIDs without lock.
			start, err := t.parentDS.AllocateIDs(key, 1)
			if !lme.Assign(i, err) {
				if realKeys == nil {
					realKeys = make([]*datastore.Key, len(keys))
					copy(realKeys, keys)
				}

				aid, ns, toks := key.Split()
				toks[len(toks)-1].IntID = start
				realKeys[i] = datastore.NewKeyToks(aid, ns, toks)
			}
		}
	}
	err := lme.Get()

	if realKeys != nil {
		return realKeys, err
	}
	return keys, err
}
Example #2
0
// ReadKey deserializes a key from the buffer. The value of context must match
// the value of context that was passed to WriteKey when the key was encoded.
// If context == WithoutContext, then the appid and namespace parameters are
// used in the decoded Key. Otherwise they're ignored.
func ReadKey(buf Buffer, context KeyContext, appid, namespace string) (ret *ds.Key, err error) {
	defer recoverTo(&err)
	actualCtx, e := buf.ReadByte()
	panicIf(e)

	actualAid, actualNS := "", ""
	if actualCtx == 1 {
		actualAid, _, e = cmpbin.ReadString(buf)
		panicIf(e)
		actualNS, _, e = cmpbin.ReadString(buf)
		panicIf(e)
	} else if actualCtx != 0 {
		err = fmt.Errorf("helper: expected actualCtx to be 0 or 1, got %d", actualCtx)
		return
	}

	if context == WithoutContext {
		// overrwrite with the supplied ones
		actualAid = appid
		actualNS = namespace
	}

	toks := []ds.KeyTok{}
	for {
		ctrlByte, e := buf.ReadByte()
		panicIf(e)
		if ctrlByte == 0 {
			break
		}
		if len(toks)+1 > ReadKeyNumToksReasonableLimit {
			err = fmt.Errorf(
				"helper: tried to decode huge key with > %d tokens",
				ReadKeyNumToksReasonableLimit)
			return
		}

		tok, e := ReadKeyTok(buf)
		panicIf(e)

		toks = append(toks, tok)
	}

	return ds.NewKeyToks(actualAid, actualNS, toks), nil
}
Example #3
0
// dsR2F (DS real-to-fake) converts an SDK Key to a ds.Key
func dsR2F(k *datastore.Key) *ds.Key {
	if k == nil {
		return nil
	}
	aid := k.AppID()
	ns := k.Namespace()

	count := 0
	for nk := k; nk != nil; nk = nk.Parent() {
		count++
	}

	toks := make([]ds.KeyTok, count)

	for ; k != nil; k = k.Parent() {
		count--
		toks[count].Kind = k.Kind()
		toks[count].StringID = k.StringID()
		toks[count].IntID = k.IntID()
	}
	return ds.NewKeyToks(aid, ns, toks)
}
func maybeIndexValue(val interface{}) interface{} {
	// It may be the SDK's datastore.indexValue structure (in datastore/load.go).
	//
	// Since this is a private type with no methods, we need to use reflection
	// to get the data out. Ick.
	rv := reflect.ValueOf(val)
	if rv.Kind() == reflect.Struct && rv.Type().String() == "datastore.indexValue" {
		rv = rv.FieldByName("value")
		if rv.IsValid() && rv.Kind() == reflect.Ptr {
			// TODO(riannucci): determine if this is how nil IndexValues are stored.
			// Maybe they're encoded as a PropertyValue with all-nil fields instead?
			if rv.IsNil() {
				return nil
			}
			rv = rv.Elem()
			// we're in protobuf land now.
			if rv.Type().Name() == "PropertyValue" {
				for i := 0; i < rv.NumField(); i++ {
					field := rv.Field(i)
					if field.Kind() == reflect.Ptr {
						if field.IsNil() {
							continue
						}
						field = field.Elem()
						switch field.Kind() {
						case reflect.Int64:
							return field.Int()
						case reflect.String:
							return field.String()
						case reflect.Bool:
							return field.Bool()
						case reflect.Float64:
							return field.Float()
						}
						switch field.Type().Name() {
						case "PropertyValue_PointValue":
							// Lat == X, Lng == Y b/c historical resons.
							return ds.GeoPoint{
								Lat: field.FieldByName("X").Float(),
								Lng: field.FieldByName("Y").Float()}
						case "PropertyValue_ReferenceValue":
							aid := field.FieldByName("App").Elem().String()
							ns := ""
							if nsf := field.FieldByName("NameSpace"); !nsf.IsNil() {
								ns = nsf.Elem().String()
							}
							elems := field.FieldByName("Pathelement")
							toks := make([]ds.KeyTok, elems.Len())
							for i := range toks {
								e := elems.Index(i).Elem()
								toks[i].Kind = e.FieldByName("Type").Elem().String()
								if iid := e.FieldByName("Id"); !iid.IsNil() {
									toks[i].IntID = iid.Elem().Int()
								}
								if sid := e.FieldByName("Name"); !sid.IsNil() {
									toks[i].StringID = sid.Elem().String()
								}
							}
							return ds.NewKeyToks(aid, ns, toks)
						}
						panic(fmt.Errorf(
							"UNKNOWN datastore.indexValue field type: %s", field.Type()))
					}
					// there's also the `XXX_unrecognized []byte` field, so don't panic
					// here.
				}
				panic(fmt.Errorf("cannot decode datastore.indexValue (no recognized field): %v", val))
			}
			panic(fmt.Errorf("cannot decode datastore.indexValue (wrong inner type): %v", val))
		}
		panic(fmt.Errorf("cannot decode datastore.indexValue: %v", val))
	} else {
		return val
	}
}