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 } }
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 }
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)} } }
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(), } }
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), } } }
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, } }
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()} }