예제 #1
0
func (self *dispatcherimpl) Perform(context *ares.Context,
	operation ares.Operation) (ret ares.Return) {
	if context == nil {
		context = new(ares.Context)
	}

	if context.Level > contextLevelMaximum {
		return &operations.GenericReturn{retcode.NewStatusError(retcode.ErrorClient,
			errors.New(fmt.Sprintf("Maximum level is %v - reconfigure buckets",
				contextLevelMaximum)))}
	}

	switch operation := operation.(type) {
	case *operations.Forwarded:
		// Is forwarded
		return self.perform_BucketOperation(context, operation.Original, operation.BucketId)
	case operations.HasTargetBucketId:
		// If it has a target bucket id, send it to that bucket.
		return self.perform_BucketOperation(context, operation, operation.TargetBucketId())
	case *operations.CreateBucket:
		return self.perform_OpCreateBucket(context, operation)
	default:
		return &operations.GenericReturn{retcode.NewStatusError(retcode.ErrorClient,
			errors.New(fmt.Sprintf("Unknown operation: %T, %v", operation, operation)))}
	}
}
예제 #2
0
func (self *notifier) createInstance(state *minos.OperationState) (
	instance *notifierInstance,
	ret retcode.Status) {

	var err error
	keysBucketId, exists, err := state.MetadataGetterSetter.Forwarder(
		true, metadataKey_keys)
	if err != nil || !exists {
		return nil, retcode.NewStatusError(
			retcode.ErrorServer, errors.New("Could not get forwarder metadata (keys)"))
	}
	registrationsBucketId, exists, err := state.MetadataGetterSetter.Forwarder(
		true, metadataKey_registrations)
	if err != nil || !exists {
		return nil, retcode.NewStatusError(
			retcode.ErrorServer, errors.New("Could not get forwarder metadata (keys)"))
	}

	ni := new(notifierInstance)
	ni.base = self
	ni.keysBucketId = keysBucketId
	ni.registrationsBucketId = registrationsBucketId

	return ni, retcode.NewStatusOk()
}
예제 #3
0
func (self *blobstorePrototype) createInstance(state *minos.OperationState) (
	instance *blobstoreStruct,
	ret retcode.Status) {

	var err error
	backendId, exists, err := state.MetadataGetterSetter.Forwarder(
		true, metadataKey_backend)
	if err != nil {
		return nil, retcode.NewStatusError(
			retcode.ErrorServer, errors.New("Could not get forwarder metadata (backend)"))
	}
	if !exists {
		return nil, retcode.NewStatusError(
			retcode.ErrorServer, errors.New("Backend bucket id not found in metadata"))
	}

	ni := new(blobstoreStruct)
	ni.incubator = new(incubator)
	ni.incubator.bucketId = backendId
	ni.public = new(public)
	ni.public.bucketId = backendId
	ni.public.incubator = ni.incubator

	return ni, retcode.NewStatusOk()
}
예제 #4
0
파일: op_put.go 프로젝트: cronosun/buranv1
func (self *Store) Op_put(operation *operations.Put) (ret bucket.BucketReturn) {
	leveldb, err := self.Database()
	if err != nil {
		return &bucket.ReturnGeneric{retcode.NewStatusError(retcode.ErrorServer, err)}
	}

	keyBytes := self.KeyToBytesAndPrefix(operation.Key)

	// Success, now forward that thing (forwarding never fails)
	if self.State.PutForwarder != nil && !self.DoNotPutForward {
		self.State.PutForwarder.ForwardIfOk(operation)
	}

	var returnValue *operations.PutReturn
	if operation.Value != nil {
		valueBytes := operation.Value.Serialize()
		//fmt.Printf("PUT: %v\n", keyBytes)

		err = leveldb.Put(keyBytes, valueBytes, nil /*TODO*/)
		if err != nil {
			return &bucket.ReturnGeneric{retcode.NewStatusError(retcode.ErrorServer, err)}
		}
		returnValue = &operations.PutReturn{retcode.NewStatusOk()}
	} else {
		// Remove operation
		err = leveldb.Delete(keyBytes, nil)
		if err != nil {
			return &bucket.ReturnGeneric{retcode.NewStatusError(retcode.ErrorServer, err)}
		}
		returnValue = &operations.PutReturn{retcode.NewStatus(retcode.OkRemove)}
	}

	return returnValue
}
예제 #5
0
func (self *directoryBucket) createInstance(state *minos.OperationState) (
	instance *directoryBucketInstance,
	ret retcode.Status) {

	var err error
	backendId, exists, err := state.MetadataGetterSetter.Forwarder(
		true, forwarder_name)
	if err != nil {
		return nil, retcode.NewStatusError(
			retcode.ErrorServer, errors.New("Could not get forwarder metadata (backend)"))
	}
	if !exists {
		return nil, retcode.NewStatusError(
			retcode.ErrorServer, errors.New("Backend bucket id not found in metadata"))
	}

	cstore := &commonstore.Store{
		DbTypeName:       levelDbTypeName,
		DatabaseProvider: self.database,
		State:            state,
		DoNotPutForward:  true,
	}

	ni := new(directoryBucketInstance)
	ni.base = self
	ni.cstore = cstore
	ni.backendId = backendId

	return ni, retcode.NewStatusOk()
}
예제 #6
0
func (self *dispatcherimpl) perform_BucketOperation(context *ares.Context,
	operation ares.Operation,
	targetBucketId bucket.Id) (
	ret ares.Return) {

	bucketId := targetBucketId

	if bucketId == nil || len(bucketId) == 0 {
		return &operations.GenericReturn{retcode.NewStatusError(retcode.ErrorClient,
			errors.New("Bucket ID is missing or invalid"))}
	}

	bucketType := self.typesRegistry.BucketType(bucketId.TypeId())
	if bucketType == nil {
		return &operations.GenericReturn{retcode.NewStatusError(retcode.ErrorClient,
			errors.New(fmt.Sprintf("BucketType %v not found", bucketId.TypeId())))}
	}

	var err error

	// Special case for metadata
	if bucketId.IsMetadata() {
		// Extract and supply the original bucket ID to the metadata
		bucketId = bucketId.ExtractOriginalId()
	}

	metadataReader, err := self.metadata.TypedGetterSetter(bucketId)
	if err != nil {
		return &operations.GenericReturn{
			retcode.NewStatusError(retcode.ErrorBucketIdNotFound, err)}
	}

	state := new(minos.OperationState)
	state.Operation = operation
	state.BucketId = bucketId

	putfowarderVar := new(putfowarder)
	putfowarderVar.metadataReader = metadataReader
	putfowarderVar.putReceiversIds, err = metadataReader.PutReceivers()
	putfowarderVar.context = *context
	putfowarderVar.forwardFunction = self.Perform

	state.PutForwarder = putfowarderVar
	state.MetadataGetterSetter = metadataReader
	state.NotificationReceiver = self.receiveNotification
	state.Context = context
	state.Dispatcher = self
	state.Locker = self.lock
	state.Files = self.files
	state.BucketType = self.typesRegistry.BucketType

	bucketReturn := bucketType.Perform(state)
	putfowarderVar.maybeDoPutForward(bucketReturn)
	return bucketReturn
}
예제 #7
0
func (self *Store) Op_iterate(operation *operations.Iterate) (
	ret bucket.BucketReturn) {

	database, err := self.Database()
	if err != nil {
		ret = &bucket.ReturnGeneric{retcode.NewStatusError(retcode.ErrorServer, err)}
		return
	}

	r, err := self.createScanRangeForIterate(operation, self.State.BucketId)
	if err != nil {
		ret = &bucket.ReturnGeneric{retcode.NewStatusError(retcode.ErrorClient, err)}
		return
	}
	iterator := database.NewIterator(r, nil)
	defer iterator.Release()

	var exhausted bool
	exhausted = !iterator.First()
	resultNumber := 0
	var numberOfErrors uint32
	numberOfErrors = 0
	for !exhausted {
		key, err := typescommon.PrefixedKeyBytesToKey(
			self.State.BucketId, iterator.Key())
		if err != nil {
			numberOfErrors++
		} else {
			value, err := types.NewArrayFromBytes(iterator.Value())
			if err != nil {
				numberOfErrors++
			} else {
				// Ok
				iterateState := new(operations.IterateState)
				iterateState.ResultNumber = uint32(resultNumber)
				iterateState.Key = key
				iterateState.Value = value

				end := operation.Function(iterateState)
				if end {
					break
				}
			}
		}
		resultNumber++
		exhausted = iterator.Next()
		exhausted = !iterator.Valid() //TODO: Why do we need this too?
	}

	return &operations.IterateReturn{
		Status:         retcode.NewStatusOk(),
		NumberOfErrors: numberOfErrors,
	}
}
예제 #8
0
func (self *dispatcherimpl) perform_OpCreateBucket(context *ares.Context,
	operation *operations.CreateBucket) (
	ret ares.Return) {

	if context.UserId.IsPublicUser() {
		return &operations.GenericReturn{retcode.NewStatusError(
			retcode.ErrorNotAllowedForPublicUser,
			errors.New("Need to be authenticated"))}
	}

	/* Validate and create */
	bucketType := self.typesRegistry.BucketType(operation.TypeId)
	if bucketType == nil {
		return &operations.GenericReturn{retcode.NewStatusError(retcode.ErrorClient,
			errors.New(fmt.Sprintf("BucketType %v not found", operation.TypeId)))}
	}
	if operation.TypeId.IsMetadata() {
		return &operations.GenericReturn{retcode.NewStatusError(retcode.ErrorClient,
			errors.New("You tried to create a metadata bucket (bucket type). That's "+
				"not possible, since metadata buckets are only 'virtual' and cannot "+
				"be created (convert a bucket ID to a metadata bucket ID to access its "+
				"metadata)."))}
	}

	createdMetadata := operation.Metadata
	if createdMetadata == nil {
		createdMetadata = make(map[string]([]byte))
	}

	createState := new(minos.CreateState)
	createState.TypeId = operation.TypeId
	createState.Metadata = self.metadata.NewMemoryTypedReaderWriter(createdMetadata)
	createState.Context = context
	createState.Dispatcher = self
	createState.Files = self.files

	status := bucketType.Create(createState)
	if !status.GetCode().IsOk() {
		return &operations.GenericReturn{status}
	}

	/* Now create the bucket */
	bucketId, err := self.metadata.Create(operation.TypeId, createdMetadata,
		context.UserId)
	if err != nil {
		// TODO: Rollback what 'bucketType.Create' did
		return &operations.GenericReturn{retcode.NewStatusError(retcode.ErrorServer, err)}
	}

	// Done
	return &operations.CreateBucketReturn{bucketId, retcode.NewStatusOk()}
}
예제 #9
0
func (self *incubator) appendDataWithoutCleanup(state *minos.OperationState,
	id string, data []byte) (ret retcode.Status) {

	// Make sure it exists (but do not remove existing)
	self.new(state, id, false)

	currentIncubationState, ret := self.information(state, id)
	if !ret.IsOk() {
		return
	}

	// Initialize the hash how we left it the last time
	hash := currentIncubationState.restoreHash()

	// Update the hash
	_, err := hash.Write(data)
	if err != nil {
		err = errors.New(fmt.Sprintf("Unable to write to hash: %v", err))
		ret = retcode.NewStatusError(retcode.ErrorServer, err)
		return
	}

	// Update the file
	filePath, ret := self.incubationFilePath(state, id)
	if !ret.IsOk() {
		return
	}
	file, err := os.OpenFile(filePath, os.O_RDWR|os.O_APPEND, 0660)
	if err != nil {
		err = errors.New(fmt.Sprintf("Unable to open incubation file: %v", err))
		ret = retcode.NewStatusError(retcode.ErrorServer, err)
		return
	}
	defer file.Close()
	_, err = file.Write(data)
	if err != nil {
		err = errors.New(fmt.Sprintf("Unable write to incubation file: %v", err))
		ret = retcode.NewStatusError(retcode.ErrorServer, err)
		return
	}

	// Ok, now update the information
	currentIncubationState.length += uint64(len(data))
	currentIncubationState.hashState = hash.Serialize()
	ret = self.writeInformation(state, id, &currentIncubationState)

	return
}
예제 #10
0
func (self *incubator) new(state *minos.OperationState,
	id string,
	removeIfAlreadyExisting bool) (ret retcode.Status) {

	// See if it already exists (and maybe remove it)
	_, ret = self.information(state, id)
	if !ret.IsOk() {
		return
	}
	alreadyFound := ret.Code != retcode.OkNotFound
	if alreadyFound && removeIfAlreadyExisting {
		// Ok, remove current
		ret = self.cleanIncubation(state, id)
		if !ret.IsOk() {
			return
		}
	}

	if !alreadyFound {
		// Create it
		hash := serializablehash.NewSha256()
		newState := new(incubationState)
		newState.length = 0
		newState.hashState = hash.Serialize()
		self.writeInformation(state, id, newState)

		// Create empty file
		filePath, retLocal := self.incubationFilePath(state, id)
		if !retLocal.IsOk() {
			ret = retLocal
			return
		}
		file, err := os.Create(filePath)
		if err != nil {
			err = errors.New(fmt.Sprintf("Unable to create incubation file: %v", err))
			ret = retcode.NewStatusError(retcode.ErrorServer, err)
			return
		}
		err = file.Close()
		if err != nil {
			err = errors.New(fmt.Sprintf("To close incubation file: %v", err))
			ret = retcode.NewStatusError(retcode.ErrorServer, err)
			return
		}
	}
	ret = retcode.NewStatusOk()
	return
}
예제 #11
0
func (self *incubator) information(state *minos.OperationState,
	id string) (incState incubationState, ret retcode.Status) {

	key := self.createInformationKey(state, id)

	apiOperation := &operations.Get{
		BucketId: self.bucketId,
		Key:      key,
	}
	opRet := state.Dispatcher.Perform(state.Context, apiOperation)
	if opRet.GetCode() != retcode.Ok {
		// Not found or a different error
		ret = opRet.GetStatus()
		return
	}

	// Ok, found it, deserialize
	retCast := opRet.(*operations.GetReturn)
	value := retCast.Value

	incState = incubationState{}
	incState.hashState = value[0]
	err := encoding.Cbor().Decode(value[1], &incState.length)
	if err != nil {
		ret = retcode.NewStatusError(retcode.ErrorServer, err)
		return
	}

	return
}
예제 #12
0
파일: public.go 프로젝트: cronosun/buranv1
func (self *public) information(state *minos.OperationState,
	hash []byte) (pubState publicState, ret retcode.Status) {

	key := self.clreatePublicKey(state, hash)

	apiOperation := &operations.Get{
		BucketId: self.bucketId,
		Key:      key,
	}
	opRet := state.Dispatcher.Perform(state.Context, apiOperation)
	if opRet.GetCode() != retcode.Ok {
		// Not found or a different error
		ret = opRet.GetStatus()
		return
	}

	// Ok, found it, deserialize
	retCast := opRet.(*operations.GetReturn)
	value := retCast.Value

	pubState = publicState{}
	pubState.data = value[0]
	err := encoding.Cbor().Decode(value[1], &pubState.length)
	if err != nil {
		ret = retcode.NewStatusError(retcode.ErrorServer, err)
		return
	}

	return
}
예제 #13
0
func (self *incubator) writeInformation(state *minos.OperationState,
	id string, incState *incubationState) (ret retcode.Status) {

	key := self.createInformationKey(state, id)

	encodedLength, err := encoding.Cbor().Encode(incState.length)
	if err != nil {
		ret = retcode.NewStatusError(retcode.ErrorServer, err)
		return
	}
	value := types.Array{incState.hashState, encodedLength}

	apiOperation := &operations.Put{
		BucketId: self.bucketId,
		Key:      key,
		Value:    value,
	}
	opRet := state.Dispatcher.Perform(state.Context, apiOperation)
	if !opRet.GetCode().IsOk() {
		// Unable to put
		ret = opRet.GetStatus()
		return
	}

	return opRet.GetStatus()
}
예제 #14
0
func (self *directoryBucket) Perform(state *minos.OperationState) (
	bucketReturn ares.Return) {

	operation := state.Operation
	instance, ret := self.createInstance(state)
	if !ret.IsOk() {
		return &bucket.ReturnGeneric{ret.GetStatus()}
	}

	switch operation := operation.(type) {
	case *operations.Put:
		// Handle internally
		return instance.opPut(operation, state)
	case *operations.Exists:
		// Forward to backing store
		return instance.cstore.Perform(state)
	case *operations.Get:
		// Forward to backing store
		return instance.cstore.Perform(state)
	case *operations.Hash:
		// Forward to backing store
		return instance.cstore.Perform(state)
	case *operations.Scan:
		// Scan is supported but has some limits
		return instance.opScan(operation, state)
	default:
		return &bucket.ReturnGeneric{retcode.NewStatusError(
			retcode.ErrorOperationNotSupported, errors.New(fmt.Sprintf(
				"Bucket operation not supported (directory): %v\n", reflect.TypeOf(operation))))}
	}
}
예제 #15
0
파일: public.go 프로젝트: cronosun/buranv1
func (self *public) writeInformation(state *minos.OperationState,
	hash []byte, pubState *publicState) (ret retcode.Status) {

	key := self.clreatePublicKey(state, hash)

	encodedLength, err := encoding.Cbor().Encode(pubState.length)
	if err != nil {
		ret = retcode.NewStatusError(retcode.ErrorServer, err)
		return
	}
	if pubState.data == nil {
		pubState.data = []byte{}
	}
	value := types.Array{pubState.data, encodedLength}
	apiOperation := &operations.Put{
		BucketId: self.bucketId,
		Key:      key,
		Value:    value,
	}
	opRet := state.Dispatcher.Perform(state.Context, apiOperation)
	if !opRet.GetCode().IsOk() {
		// Unable to put
		ret = opRet.GetStatus()
		return
	}

	return opRet.GetStatus()
}
예제 #16
0
func (self *Store) Op_exists(operation *operations.Exists) (ret bucket.BucketReturn) {
	database, err := self.Database()
	if err != nil {
		return &bucket.ReturnGeneric{retcode.NewStatusError(retcode.ErrorServer, err)}
	}

	keyBytes := self.KeyToBytesAndPrefix(operation.Key)

	_, err = database.Get(keyBytes, nil)
	if err == leveldb.ErrNotFound {
		return &operations.ExistsReturn{retcode.NewStatus(retcode.OkNotFound)}
	}
	if err != nil {
		return &bucket.ReturnGeneric{retcode.NewStatusError(retcode.ErrorServer, err)}
	}

	return &operations.ExistsReturn{
		Status: retcode.NewStatusOk(),
	}
}
예제 #17
0
func (self *directoryBucket) Create(state *minos.CreateState) (status retcode.Status) {

	suppliedForwarder, suppliedForwarderExists, err :=
		state.Metadata.Forwarder(true, forwarder_name)
	if err != nil {
		return retcode.NewStatusError(
			retcode.ErrorClient, errors.New(fmt.Sprintf(
				"Error getting the supplied forwarder: %v\n", err)))
	}
	if suppliedForwarderExists {
		// No need to create one, already have one. Is the type correct?
		if suppliedForwarder.TypeId() != bucket.TypeId_BlobStore {
			return retcode.NewStatusError(
				retcode.ErrorClient, errors.New(fmt.Sprintf(
					"The supplied forwarder has to be of type blobstore, but it's: %v\n",
					suppliedForwarder.TypeId())))
		}
	} else {
		// We have to create the backend bucket
		createBucket := operations.CreateBucket{
			TypeId: bucket.TypeId_BlobStore,
		}
		retBackendBucket := state.Dispatcher.Perform(state.Context, &createBucket)
		if !retBackendBucket.GetCode().IsOk() {
			return retBackendBucket.GetStatus()
		}

		backendBucket := retBackendBucket.(*operations.CreateBucketReturn)

		var err error
		err = state.Metadata.SetForwarder(true, forwarder_name, backendBucket.Id)
		if err != nil {
			return retcode.NewStatusError(
				retcode.ErrorServer, errors.New(fmt.Sprintf(
					"Could not modify metadata: %v\n", err)))
		}
	}

	// Nothing to do here
	return retcode.NewStatusOk()
}
예제 #18
0
func (self *incubator) incubationFilePath(state *minos.OperationState,
	id string) (fname string, ret retcode.Status) {

	clientIdAsBase32 := encoding.Base32Encode([]byte(state.Context.ClientId))
	fname, err := state.Files.Filename(self.bucketId, "_"+clientIdAsBase32, id)
	if err != nil {
		ret = retcode.NewStatusError(retcode.ErrorServer, err)
		return
	}
	ret = retcode.NewStatusOk()
	return
}
예제 #19
0
파일: hasher.go 프로젝트: cronosun/buranv1
func (self *hasherStruct) createInstance(state *minos.OperationState) (
	instance *hasherInstance,
	ret retcode.Status) {

	var err error
	backendId, exists, err := state.MetadataGetterSetter.Forwarder(
		true, metadataKey_backend)
	if err != nil {
		return nil, retcode.NewStatusError(
			retcode.ErrorServer, errors.New("Could not get forwarder metadata (backend)"))
	}
	if !exists {
		return nil, retcode.NewStatusError(
			retcode.ErrorServer, errors.New("Backend bucket id not found in metadata"))
	}

	ni := new(hasherInstance)
	ni.base = self
	ni.backendId = backendId

	return ni, retcode.NewStatusOk()
}
예제 #20
0
파일: public.go 프로젝트: cronosun/buranv1
func (self *public) publicFilePath(state *minos.OperationState,
	hash []byte) (fname string, ret retcode.Status) {

	hashAsBase32 := encoding.Base32Encode(hash)
	firstBytesAsDirectory := hashAsBase32[:6]
	fname, err := state.Files.Filename(self.bucketId,
		firstBytesAsDirectory, hashAsBase32)
	if err != nil {
		ret = retcode.NewStatusError(retcode.ErrorServer, err)
		return
	}
	ret = retcode.NewStatusOk()
	return
}
예제 #21
0
파일: op_get.go 프로젝트: cronosun/buranv1
func (self *Store) Op_get(operation *operations.Get) (ret bucket.BucketReturn) {
	database, err := self.Database()
	if err != nil {
		return &bucket.ReturnGeneric{retcode.NewStatusError(retcode.ErrorServer, err)}
	}

	keyBytes := self.KeyToBytesAndPrefix(operation.Key)
	value, err := database.Get(keyBytes, nil)
	if err == leveldb.ErrNotFound {
		return &bucket.ReturnGeneric{retcode.NewStatus(retcode.OkNotFound)}
	}
	if err != nil {
		return &bucket.ReturnGeneric{retcode.NewStatusError(retcode.ErrorServer, err)}
	}
	keyConstructed, err := types.NewArrayFromBytes(value)
	if err != nil {
		return &bucket.ReturnGeneric{retcode.NewStatusError(retcode.ErrorServer, err)}
	}

	return &operations.GetReturn{
		Status: retcode.NewStatusOk(),
		Value:  keyConstructed,
	}
}
예제 #22
0
func (self *notifier) Create(state *minos.CreateState) (
	status retcode.Status) {

	// We have to create two buckets here
	createBucket := operations.CreateBucket{
		TypeId: bucket.TypeId_Store,
	}
	retRegistrationsBucket := state.Dispatcher.Perform(state.Context, &createBucket)
	if !retRegistrationsBucket.GetCode().IsOk() {
		return retRegistrationsBucket.GetStatus()
	}
	retKeysBucket := state.Dispatcher.Perform(state.Context, &createBucket)
	if !retKeysBucket.GetCode().IsOk() {
		return retKeysBucket.GetStatus()
	}

	registrationsBucket := retRegistrationsBucket.(*operations.CreateBucketReturn)
	keysBucket := retKeysBucket.(*operations.CreateBucketReturn)

	var err error
	err = state.Metadata.SetForwarder(true, metadataKey_registrations, registrationsBucket.Id)
	if err != nil {
		return retcode.NewStatusError(
			retcode.ErrorServer, errors.New(fmt.Sprintf(
				"Could not modify metadata: %v\n", err)))
	}
	err = state.Metadata.SetForwarder(true, metadataKey_keys, keysBucket.Id)
	if err != nil {
		return retcode.NewStatusError(
			retcode.ErrorServer, errors.New(fmt.Sprintf(
				"Could not modify metadata: %v\n", err)))
	}

	// Nothing to do here
	return retcode.NewStatusOk()
}
예제 #23
0
파일: op_put.go 프로젝트: cronosun/buranv1
func (self *notifierInstance) op_put(operation *operations.Put,
	state *minos.OperationState) (ret bucket.BucketReturn) {

	numberOfKeyElements := len(operation.Key)
	if numberOfKeyElements > 255 {
		retStatus := retcode.NewStatusError(
			retcode.ErrorClient, errors.New("Have too many elements in key"))
		return &bucket.ReturnGeneric{retStatus}
	}

	// Trigger also parent key elements
	for numberOfKeyElementsForTrigger := numberOfKeyElements; numberOfKeyElementsForTrigger >= 0; numberOfKeyElementsForTrigger-- {

		isOriginalLength := numberOfKeyElementsForTrigger == numberOfKeyElements
		keysToMatch := operation.Key[:numberOfKeyElementsForTrigger]

		if isOriginalLength {
			// Is executed first

			// First match those that have 'matchChildKeys' to false
			ret = self.triggerSubscribers(operation, keysToMatch, false, state)
			if !ret.GetCode().IsOk() {
				// Error
				return
			}

			// Now match those that have 'matchChildKeys' to true
			ret = self.triggerSubscribers(operation, keysToMatch, true, state)
			if !ret.GetCode().IsOk() {
				// Error
				return
			}
		} else {
			// We left the original key length, we now trigger the subscriptions
			// that have less key elements
			ret = self.triggerSubscribers(operation, keysToMatch, true, state)
			if !ret.GetCode().IsOk() {
				// Error
				return
			}
		}
	}

	return
}
예제 #24
0
func (self *notifierInstance) putToRegistrationBucket(state *minos.OperationState,
	operation *operations.Subscribe) (subscriptionId operations.SubscriptionId,
	status retcode.Status) {

	// Locks, so we do not generate duplicate IDs
	state.Locker.BucketIdWriteLock(self.registrationsBucketId)
	defer state.Locker.BucketIdWriteUnlock(self.registrationsBucketId)

	var err error
	for index := 0; index < numberOfSubscriptionIdGenRetries; index++ {
		subscriptionId, err = createSubscriptionIdCandidate()
		if err == nil {
			key := types.Key{[]byte(state.Context.ClientId),
				[]byte(subscriptionId)}
			opGet := operations.Get{
				BucketId: self.registrationsBucketId,
				Key:      key,
			}
			opGetApiRet := state.Dispatcher.Perform(state.Context, &opGet)
			if opGetApiRet.GetCode() == retcode.OkNotFound {
				// Great, entry not found, so add it
				keyInOperationAsArray := operation.Key.ToArray()
				value := make([][]byte, len(keyInOperationAsArray)+1)
				value[0] = []byte{serializeMatchChildKey(operation.MatchChildKeys)}
				copy(value[1:], keyInOperationAsArray)

				opPut := operations.Put{
					BucketId: self.registrationsBucketId,
					Key:      key,
					Value:    value,
				}
				opPutApiRet := state.Dispatcher.Perform(state.Context, &opPut)
				if opPutApiRet.GetCode().IsOk() {
					// Great, registration is OK
					status = retcode.NewStatusOk()
					return
				}
			}
		}
	}
	return nil, retcode.NewStatusError(retcode.ErrorServer,
		errors.New("No free subscription ID found"))
}
예제 #25
0
func (self *notifier) Perform(state *minos.OperationState) (
	bucketReturn ares.Return) {
	operation := state.Operation

	ni, ret := self.createInstance(state)
	if !ret.GetCode().IsOk() {
		return &bucket.ReturnGeneric{ret.GetStatus()}
	}

	switch operation := operation.(type) {
	case *operations.Put:
		return ni.op_put(operation, state)
	case *operations.Subscribe:
		return ni.op_subscribe(operation, state)
	case *operations.Unsubscribe:
		return ni.op_unsubscribe(operation, state)
	default:
		return &bucket.ReturnGeneric{retcode.NewStatusError(
			retcode.ErrorOperationNotSupported, errors.New(fmt.Sprintf(
				"Bucket operation not supported (notifier): %v\n", reflect.TypeOf(operation))))}
	}
}
예제 #26
0
func (self *Store) Perform(state *minos.OperationState) (
	bucketReturn ares.Return) {
	operation := state.Operation

	switch operation.(type) {
	case *operations.Put:
		return self.Op_put(operation.(*operations.Put))
	case *operations.Get:
		return self.Op_get(operation.(*operations.Get))
	case *operations.Hash:
		return self.Op_hash(operation.(*operations.Hash))
	case *operations.Scan:
		return self.Op_scan(operation.(*operations.Scan))
	case *operations.Iterate:
		return self.Op_iterate(operation.(*operations.Iterate))
	case *operations.Exists:
		return self.Op_exists(operation.(*operations.Exists))
	default:
		return &bucket.ReturnGeneric{retcode.NewStatusError(
			retcode.ErrorClient, errors.New(fmt.Sprintf(
				"Unknown bucket operatiion (store): %v\n", reflect.TypeOf(operation))))}
	}
}
예제 #27
0
func createKeyForLookupBucket(
	matchChildKeys bool,
	subscriptionId operations.SubscriptionId,
	subscriptionKey types.Key,
	state *minos.OperationState) (key types.Key, ret retcode.Status) {

	numberOfKeyElements := len(subscriptionKey)
	if numberOfKeyElements > 255 {
		ret = retcode.NewStatusError(retcode.ErrorClient,
			errors.New("Too many key elements"))
		return
	}

	matchChildKeysByte := serializeMatchChildKey(matchChildKeys)

	newKey := make(types.Key, numberOfKeyElements+4)
	newKey[0] = []byte{matchChildKeysByte}
	newKey[1] = []byte{byte(numberOfKeyElements)}
	copy(newKey[2:], subscriptionKey)
	newKey[2+numberOfKeyElements] = []byte(state.Context.ClientId)
	newKey[3+numberOfKeyElements] = []byte(subscriptionId)
	return newKey, retcode.NewStatusOk()
}
예제 #28
0
파일: op_put.go 프로젝트: cronosun/buranv1
func (self *blobstoreStruct) op_put(operation *operations.Put,
	state *minos.OperationState) (ret bucket.BucketReturn) {

	commonOp := new(commonOperation)
	retStatus := commonOp.fill(operation.Key, operation.Value)
	if !retStatus.IsOk() {
		return &bucket.ReturnGeneric{retStatus}
	}

	var status retcode.Status
	switch commonOp.operation {
	case operation_incubation_append:
		if len(commonOp.value) != 1 {
			panic("When calling append, need exactly one value (data to append)")
		}
		status = self.incubator.appendData(state, commonOp.incubationId,
			commonOp.value[0])
	case operation_incubation_cancel:
		status = self.incubator.cleanIncubation(state, commonOp.incubationId)
	case operation_incubation_finish:
		status = self.public.publish(state, commonOp.incubationId)
	case operation_incubation_new:
		status = self.incubator.new(state, commonOp.incubationId, true)
	default:
		err := errors.New(fmt.Sprintf("Unknown operation: operation-code: "+
			"%v (this usually means you called PUT instead of GET). Key: %v\n",
			commonOp.operation, operation.Key))
		status = retcode.NewStatusError(retcode.ErrorClient, err)
	}

	// Done, return
	if status.IsOk() {
		return &operations.PutReturn{status}
	} else {
		return &bucket.ReturnGeneric{status}
	}
}
예제 #29
0
파일: op_get.go 프로젝트: cronosun/buranv1
func (self *counterInstance) op_get(operation *operations.Get) (
	ret bucket.BucketReturn) {

	get_return := self.cstore.Op_get(operation)
	if get_return.GetCode() == retcode.OkNotFound {
		// This is a special case, if non existent, return 0
		zeroValue := 0
		valueBytes, err := encoding.Cbor().Encode(zeroValue)
		if err != nil {
			return &bucket.ReturnGeneric{retcode.NewStatusError(retcode.ErrorServer,
				errors.New(fmt.Sprintf("Could not encode cbor", err)))}
		}

		value := types.Array{valueBytes}
		get_return := operations.GetReturn{
			Status: retcode.NewStatusOk(),
			Value:  value,
		}
		return &get_return
	} else {
		// Everything else is returned 1:1
		return get_return
	}
}
예제 #30
0
func (self *blobstorePrototype) Create(state *minos.CreateState) (status retcode.Status) {

	// We have to create the backend bucket
	createBucket := operations.CreateBucket{
		TypeId: bucket.TypeId_Store,
	}
	retBackendBucket := state.Dispatcher.Perform(state.Context, &createBucket)
	if !retBackendBucket.GetCode().IsOk() {
		return retBackendBucket.GetStatus()
	}

	backendBucket := retBackendBucket.(*operations.CreateBucketReturn)

	var err error
	err = state.Metadata.SetForwarder(true, metadataKey_backend, backendBucket.Id)
	if err != nil {
		return retcode.NewStatusError(
			retcode.ErrorServer, errors.New(fmt.Sprintf(
				"Could not modify metadata: %v\n", err)))
	}

	// Nothing to do here
	return retcode.NewStatusOk()
}