Ejemplo n.º 1
0
func (self *hasherStruct) 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.(type) {
	case *operations.Put:
		return instance.op_put(operation.(*operations.Put), state)
	case *operations.Scan:
		// Scan is disallowed for security reasons
		return &bucket.ReturnGeneric{
			Status: retcode.NewStatus(retcode.ErrorOperationNotSupported),
		}
	default:
		// All other operations are forwarded
		apiOperation := operations.Forwarded{
			BucketId: instance.backendId,
			Original: state.Operation,
		}
		apiReturn := state.Dispatcher.Perform(state.Context, &apiOperation)
		return apiReturn
	}
}
Ejemplo n.º 2
0
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
}
Ejemplo n.º 3
0
func (self *notifierInstance) triggerSubscribers(operation *operations.Put,
	keysToMatch types.Key,
	matchChildKeys bool,
	state *minos.OperationState) (ret bucket.BucketReturn) {

	numberOfKeyElements := len(keysToMatch)

	matchChildKeysByte := serializeMatchChildKey(matchChildKeys)

	lookupKeyBegin := make(types.Key, numberOfKeyElements+3)
	lookupKeyBegin[0] = []byte{matchChildKeysByte}
	lookupKeyBegin[1] = []byte{byte(numberOfKeyElements)}
	copy(lookupKeyBegin[2:], keysToMatch)
	lookupKeyBegin[len(lookupKeyBegin)-1] = []byte{}

	lookupKeyEnd := make(types.Key, numberOfKeyElements+3)
	lookupKeyEnd[0] = []byte{matchChildKeysByte}
	lookupKeyEnd[1] = []byte{byte(numberOfKeyElements)}
	copy(lookupKeyEnd[2:], keysToMatch)
	lookupKeyEnd[len(lookupKeyEnd)-1] = []byte{255}

	is := new(iterateState)
	is.opPut = operation
	is.notificationReceiver = state.NotificationReceiver
	is.id = state.BucketId

	opIterate := &operations.Iterate{
		BucketId: self.keysBucketId,
		From: operations.Bound{
			Key: lookupKeyBegin,
		},
		To: &operations.Bound{
			Key: lookupKeyEnd,
		},
		Function: is.iterateFunction,
	}
	apiReturn := state.Dispatcher.Perform(state.Context, opIterate)
	if !apiReturn.GetCode().IsOk() {
		return &bucket.ReturnGeneric{apiReturn.GetStatus()}
	}

	if operation.Value != nil {
		return &operations.PutReturn{retcode.NewStatusOk()}
	} else {
		return &operations.PutReturn{retcode.NewStatus(retcode.OkRemove)}
	}
}
Ejemplo n.º 4
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(),
	}
}
Ejemplo n.º 5
0
func (self *blobstorePrototype) 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.(type) {
	case *operations.Put:
		return instance.op_put(operation.(*operations.Put), state)
	case *operations.Get:
		return instance.op_get(operation.(*operations.Get), state)
	default:
		// No other operations are supported in this bucket type
		return &bucket.ReturnGeneric{
			Status: retcode.NewStatus(retcode.ErrorOperationNotSupported),
		}
	}
}
Ejemplo n.º 6
0
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,
	}
}
Ejemplo n.º 7
0
func (self *hasherInstance) op_put(operation *operations.Put,
	state *minos.OperationState) (ret bucket.BucketReturn) {

	if operation.Value == nil {
		// Removes are ignored
		return &bucket.ReturnGeneric{retcode.NewStatus(retcode.ErrorOperationNotSupported)}
	}

	var firstElementHashBytes []byte
	if operation.Hashes.FirstElementSha256Hash == nil {
		theHasher := syshasher.NewHasher(operation.Value)
		firstElementHashBytes = theHasher.FirstElement()
		//TODO: Also forward alle elements hash
	}
	firstElementHash := hashes.FirstElementSha256Hash(firstElementHashBytes)

	// Always forward a put with the generated hash as value, even if already exists
	//TODO: Security problem if someone listens for such things?
	putForward := operations.Put{
		Key:   operation.Key,
		Value: types.Array{firstElementHashBytes},
		Hashes: hashes.Hashes{
			FirstElementSha256Hash: firstElementHash,
		},
	}
	state.PutForwarder.ForwardIfOk(&putForward)

	// Check if already exists
	existsOperation := operations.Exists{
		BucketId: self.backendId,
		Key:      types.Key{firstElementHashBytes},
	}
	apiExists := state.Dispatcher.Perform(state.Context, &existsOperation)
	if apiExists.GetCode() == retcode.Ok {
		// Already exists, end here
		return &operations.PutReturn{retcode.NewStatus(retcode.OkAlreadyExists)}
	}

	if !apiExists.GetCode().IsOk() {
		return &bucket.ReturnGeneric{retcode.NewStatusError(
			apiExists.GetCode(),
			errors.New("Unable to check if the entry already exists"))}
	}

	originalValue := operation.Value
	var valueToSupply []byte
	if len(originalValue) > 0 {
		valueToSupply = originalValue[0]
	} else {
		// If there's no value, take empty bytes
		valueToSupply = []byte{}
	}

	newPutOperation := operations.Put{
		BucketId: self.backendId,
		Key:      types.Key{firstElementHashBytes},
		// Only the first element survives
		Value: types.Array{valueToSupply},
	}

	apiPerformRet := state.Dispatcher.Perform(state.Context, &newPutOperation)
	if !apiPerformRet.GetCode().IsOk() {
		return &bucket.ReturnGeneric{retcode.NewStatusError(
			apiPerformRet.GetCode(),
			errors.New("Unable to transfer the data to the backend bucket"))}
	}

	return &bucket.ReturnGeneric{retcode.NewStatusOk()}
}