First commit
This commit is contained in:
25
setup/dbaas/.gitattributes
vendored
Normal file
25
setup/dbaas/.gitattributes
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files you want to always be normalized
|
||||
# and converted to native line endings on checkout.
|
||||
*.c text diff=cpp
|
||||
*.cpp text diff=cpp
|
||||
*.css text
|
||||
*.go text diff=golang
|
||||
*.htm text diff=html
|
||||
*.html text diff=html
|
||||
*.java text diff=java
|
||||
*.js text
|
||||
*.jsp text
|
||||
*.less text
|
||||
*.properties text
|
||||
*.py text diff=python
|
||||
*.sql text
|
||||
*.xml text
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.png binary
|
||||
*.jpg binary
|
3
setup/dbaas/.gitignore
vendored
Normal file
3
setup/dbaas/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# documentation
|
||||
.tox
|
||||
docs/_build/
|
4
setup/dbaas/.gitreview
Normal file
4
setup/dbaas/.gitreview
Normal file
@@ -0,0 +1,4 @@
|
||||
[gerrit]
|
||||
host=gerrit.o-ran-sc.org
|
||||
port=29418
|
||||
project=ric-plt/dbaas.git
|
16
setup/dbaas/.readthedocs.yaml
Normal file
16
setup/dbaas/.readthedocs.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
version: 2
|
||||
|
||||
formats:
|
||||
- htmlzip
|
||||
|
||||
build:
|
||||
image: latest
|
||||
|
||||
python:
|
||||
version: 3.7
|
||||
install:
|
||||
- requirements: docs/requirements-docs.txt
|
||||
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
68
setup/dbaas/INFO.yaml
Normal file
68
setup/dbaas/INFO.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
project: 'ric_plt_dbaas'
|
||||
project_creation_date: '2019-11-08'
|
||||
project_category: ''
|
||||
lifecycle_state: 'Incubation'
|
||||
project_lead: &oran_ric_plt_dbaas_ptl
|
||||
name: 'Thoralf Czichy'
|
||||
email: 'thoralf.czichy@nokia.com'
|
||||
id: 'czichy'
|
||||
company: 'Nokia'
|
||||
timezone: 'America/New_York'
|
||||
primary_contact: *oran_ric_plt_dbaas_ptl
|
||||
issue_tracking:
|
||||
type: 'jira'
|
||||
url: 'https://jira.o-ran-sc.org/projects/'
|
||||
key: 'ric_plt_dbaas'
|
||||
mailing_list:
|
||||
type: 'groups.io'
|
||||
url: 'technical-discuss@lists.o-ran-sc.org'
|
||||
tag: '[]'
|
||||
realtime_discussion:
|
||||
type: 'irc'
|
||||
server: 'freenode.net'
|
||||
channel: '#oran'
|
||||
meetings:
|
||||
- type: 'gotomeeting+irc'
|
||||
agenda: 'https://wiki.o-ran-sc.org/display/'
|
||||
url: ''
|
||||
server: 'freenode.net'
|
||||
channel: '#oran'
|
||||
repeats: ''
|
||||
time: ''
|
||||
repositories:
|
||||
- ric-plt/dbaas
|
||||
committers:
|
||||
- <<: *oran_ric_plt_dbaas_ptl
|
||||
- name: 'makiaija'
|
||||
email: 'jussi.maki-aijala@nokia.com'
|
||||
company: 'nokia'
|
||||
id: 'makiaija'
|
||||
timezone: 'Unknown/Unknown'
|
||||
- name: 'Marco Tallskog'
|
||||
email: 'marco.tallskog@nokia.com'
|
||||
company: 'nokia'
|
||||
id: 'tallskog'
|
||||
timezone: 'Unknown/Unknown'
|
||||
- name: 'Timo Tietavainen'
|
||||
email: 'timo.tietavainen@nokia.com'
|
||||
company: 'nokia'
|
||||
id: 'tietavai'
|
||||
timezone: 'Unknown/Unknown'
|
||||
- name: 'Rolf Badorek'
|
||||
email: 'rolf.badorek@nokia.com'
|
||||
company: 'nokia'
|
||||
id: 'badorek'
|
||||
timezone: 'Unknown/Unknown'
|
||||
- name: 'Arvo Heinonen'
|
||||
email: 'arvo.heinonen@nokia.com'
|
||||
company: 'nokia'
|
||||
id: 'arvo.heinonen'
|
||||
timezone: 'Unknown/Unknown'
|
||||
tsc:
|
||||
# yamllint disable rule:line-length
|
||||
approval: 'missing'
|
||||
changes:
|
||||
- type: ''
|
||||
name: ''
|
||||
link: ''
|
34
setup/dbaas/LICENSES.txt
Normal file
34
setup/dbaas/LICENSES.txt
Normal file
@@ -0,0 +1,34 @@
|
||||
LICENSES.txt
|
||||
|
||||
|
||||
Unless otherwise specified, all software contained herein is licensed
|
||||
under the Apache License, Version 2.0 (the "Software License");
|
||||
you may not use this software except in compliance with the Software
|
||||
License. You may obtain a copy of the Software License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the Software License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the Software License for the specific language governing permissions
|
||||
and limitations under the Software License.
|
||||
|
||||
|
||||
|
||||
Unless otherwise specified, all documentation contained herein is licensed
|
||||
under the Creative Commons License, Attribution 4.0 Intl. (the
|
||||
"Documentation License"); you may not use this documentation except in
|
||||
compliance with the Documentation License. You may obtain a copy of the
|
||||
Documentation License at
|
||||
|
||||
https://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
Unless required by applicable law or agreed to in writing, documentation
|
||||
distributed under the Documentation License is distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the Documentation License for the specific language governing
|
||||
permissions and limitations under the Documentation License.
|
||||
|
||||
|
||||
|
122
setup/dbaas/README.md
Normal file
122
setup/dbaas/README.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# Database as a service repository
|
||||
|
||||
This repository containes all the needed elements to deploy database as a service to kubernetes
|
||||
|
||||
## Architecture
|
||||
|
||||
Redis is the chosen database technology and the final product will deploy autonomous
|
||||
redis cluster. In R0 schedule, single, non-redundant, non-persistent redis server is
|
||||
deployed
|
||||
|
||||
## Subsystem structure
|
||||
|
||||
**docker** Contains dockerfiles to produce dbaas / testapplication container images
|
||||
**charts** Contais helm charts to deploy dbaas service / testapplication
|
||||
**testapplication** Contains dbaas test applications with various languages such as go, ..
|
||||
|
||||
## Container image creation
|
||||
|
||||
The images must be built at subsystem root level
|
||||
|
||||
To produce dbaas service image:
|
||||
```
|
||||
docker build --file docker/Dockerfile.redis --tag redis-standalone .
|
||||
```
|
||||
|
||||
To produce testapplication image:
|
||||
```
|
||||
docker build --file docker/Dockerfile.testapp --tag dbaas-test .
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
### DBaaS service
|
||||
|
||||
In R0, dbaas service is realized with single container running redis database.
|
||||
The database is configured to be non-persistent and non-redundant. The container
|
||||
exposes single port which is hardcoded to be 6379.
|
||||
|
||||
After dbaas service is installed, environment variables **DBAAS_SERVICE_HOST**
|
||||
and **DBAAS_SERVICE_PORT** are exposed to application containers. SDL library
|
||||
will automatically use these environment variables.
|
||||
|
||||
The service is installed via helm by using dbaas-service chart. Modify the
|
||||
values accordingly before installation (repository location, image name, ..)
|
||||
|
||||
```
|
||||
helm install ./dbaas-service
|
||||
```
|
||||
|
||||
### DBaaS test application
|
||||
|
||||
Test application is installed via helm by using dbaas-test chart. Modify the
|
||||
values accordingly before installation (repository location, image name, ..)
|
||||
|
||||
```
|
||||
helm install ./dbaas-test
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Make sure that dbaas-service and dbaas-test application are deployed:
|
||||
```
|
||||
>>helm ls
|
||||
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
angry-greyhound 1 Thu Mar 21 11:36:23 2019 DEPLOYED dbaas-test-0.1.0 1.0 default
|
||||
loitering-toad 1 Thu Mar 21 11:35:21 2019 DEPLOYED dbaas-0.1.0 1.0 default
|
||||
```
|
||||
|
||||
Check the deployed pods
|
||||
```
|
||||
>>kubectl get pods
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
dbaas-test-app-7695dbb9ff-qn8c2 1/1 Running 0 5s
|
||||
redis-standalone-78978f4c6f-54b2s 1/1 Running 0 66s
|
||||
```
|
||||
|
||||
Connect to the test application container:
|
||||
```
|
||||
kubectl exec -it dbaas-test-app-7695dbb9ff-qn8c2 -- /bin/bash
|
||||
```
|
||||
|
||||
In test application container:
|
||||
```
|
||||
The environment variables for database backend should be set:
|
||||
|
||||
>>printenv
|
||||
DBAAS_SERVICE_HOST=10.108.103.51
|
||||
DBAAS_SERVICE_PORT=6379
|
||||
|
||||
|
||||
Go test application using preliminary go SDL-API should be able to perform reads and writes:
|
||||
|
||||
>>./testapp
|
||||
key1:data1
|
||||
key3:%!s(<nil>)
|
||||
key2:data2
|
||||
num1:1
|
||||
num2:2
|
||||
-------------
|
||||
mix2:2
|
||||
num1:1
|
||||
num2:2
|
||||
pair1:data1
|
||||
array1:adata1
|
||||
mix1:data1
|
||||
mix3:data3
|
||||
mix4:4
|
||||
arr1:
|
||||
key1:data1
|
||||
key2:data2
|
||||
pair2:data2
|
||||
array2:adata2
|
||||
|
||||
|
||||
Redis server can be pinged with redis-cli:
|
||||
|
||||
>>redis-cli -h $DBAAS_SERVICE_HOST -p $DBAAS_SERVICE_PORT ping
|
||||
PONG
|
||||
```
|
||||
|
||||
## License
|
||||
This project is licensed under the Apache License 2.0 - see the [LICENSE.md](LICENSE.md) file for details
|
25
setup/dbaas/charts/dbaas-service/Chart.yaml
Normal file
25
setup/dbaas/charts/dbaas-service/Chart.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
# Copyright (c) 2019 AT&T Intellectual Property.
|
||||
# Copyright (c) 2019 Nokia.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
# platform project (RICP).
|
||||
#
|
||||
|
||||
apiVersion: v1
|
||||
appVersion: "1.0"
|
||||
description: DBaaS realized with standalone, non-persistent, non-redundant Redis
|
||||
name: dbaas
|
||||
version: 0.1.0
|
39
setup/dbaas/charts/dbaas-service/templates/deployment.yaml
Normal file
39
setup/dbaas/charts/dbaas-service/templates/deployment.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copyright (c) 2019 AT&T Intellectual Property.
|
||||
# Copyright (c) 2019 Nokia.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
# platform project (RICP).
|
||||
#
|
||||
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .Values.backend.name }}
|
||||
spec:
|
||||
replicas: {{ .Values.backend.replicas }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ .Values.backend.name }}
|
||||
spec:
|
||||
terminationGracePeriodSeconds: {{ .Values.backend.terminationGracePeriodSeconds }}
|
||||
containers:
|
||||
- image: {{ .Values.backend.image.name }}:{{ .Values.backend.image.tag }}
|
||||
imagePullPolicy: {{ .Values.backend.image.imagePullPolicy }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.backend.targetPort }}
|
||||
name: {{ .Values.backend.name }}
|
||||
restartPolicy: Always
|
30
setup/dbaas/charts/dbaas-service/templates/service.yaml
Normal file
30
setup/dbaas/charts/dbaas-service/templates/service.yaml
Normal file
@@ -0,0 +1,30 @@
|
||||
# Copyright (c) 2019 AT&T Intellectual Property.
|
||||
# Copyright (c) 2019 Nokia.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
# platform project (RICP).
|
||||
#
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .Chart.Name }}
|
||||
spec:
|
||||
selector:
|
||||
app: {{ .Values.backend.name }}
|
||||
ports:
|
||||
- port: {{ .Values.backend.port }}
|
||||
targetPort: {{ .Values.backend.targetPort }}
|
30
setup/dbaas/charts/dbaas-service/values.yaml
Normal file
30
setup/dbaas/charts/dbaas-service/values.yaml
Normal file
@@ -0,0 +1,30 @@
|
||||
# Copyright (c) 2019 AT&T Intellectual Property.
|
||||
# Copyright (c) 2019 Nokia.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
# platform project (RICP).
|
||||
#
|
||||
|
||||
backend:
|
||||
terminationGracePeriodSeconds: 0
|
||||
replicas: 1
|
||||
name: "redis-standalone"
|
||||
port: 6379
|
||||
targetPort: 6379
|
||||
image:
|
||||
name: snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com/redis-standalone
|
||||
tag: latest
|
||||
imagePullPolicy: IfNotPresent
|
25
setup/dbaas/charts/dbaas-test/Chart.yaml
Normal file
25
setup/dbaas/charts/dbaas-test/Chart.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
# Copyright (c) 2019 AT&T Intellectual Property.
|
||||
# Copyright (c) 2019 Nokia.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
# platform project (RICP).
|
||||
#
|
||||
|
||||
apiVersion: v1
|
||||
appVersion: "1.0"
|
||||
description: Application for testing DBAAS connectivity
|
||||
name: dbaas-test
|
||||
version: 0.1.0
|
37
setup/dbaas/charts/dbaas-test/templates/deployment.yaml
Normal file
37
setup/dbaas/charts/dbaas-test/templates/deployment.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
# Copyright (c) 2019 AT&T Intellectual Property.
|
||||
# Copyright (c) 2019 Nokia.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
# platform project (RICP).
|
||||
#
|
||||
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .Values.testapp.name }}
|
||||
spec:
|
||||
replicas: {{ .Values.testapp.replicas }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ .Values.testapp.name }}
|
||||
spec:
|
||||
terminationGracePeriodSeconds: {{ .Values.testapp.terminationGracePeriodSeconds }}
|
||||
containers:
|
||||
- image: {{ .Values.testapp.image.name }}:{{ .Values.testapp.image.tag }}
|
||||
imagePullPolicy: {{ .Values.testapp.image.imagePullPolicy }}
|
||||
name: {{ .Values.testapp.name }}
|
||||
restartPolicy: Always
|
28
setup/dbaas/charts/dbaas-test/values.yaml
Normal file
28
setup/dbaas/charts/dbaas-test/values.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
# Copyright (c) 2019 AT&T Intellectual Property.
|
||||
# Copyright (c) 2019 Nokia.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
# platform project (RICP).
|
||||
#
|
||||
|
||||
testapp:
|
||||
terminationGracePeriodSeconds: 0
|
||||
replicas: 1
|
||||
name: "dbaas-test-app"
|
||||
image:
|
||||
name: snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com/dbaas-test
|
||||
tag: latest
|
||||
imagePullPolicy: IfNotPresent
|
5
setup/dbaas/container-tag.yaml
Normal file
5
setup/dbaas/container-tag.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
# The Jenkins job requires a tag to build the Docker image.
|
||||
# This file is expected to be in the docker build directory;
|
||||
# can be moved with suitable JJB configuration.
|
||||
---
|
||||
tag: '0.4.1'
|
77
setup/dbaas/docker/Dockerfile.redis
Normal file
77
setup/dbaas/docker/Dockerfile.redis
Normal file
@@ -0,0 +1,77 @@
|
||||
# Copyright (c) 2019 AT&T Intellectual Property.
|
||||
# Copyright (c) 2019 Nokia.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
# platform project (RICP).
|
||||
#
|
||||
|
||||
|
||||
# Alpine-linux based containers use musl implementation of libc which causes
|
||||
# valgrind to emit false positives. Therefore we run UT with valgrind in
|
||||
# a separate build stage that uses ubuntu container with GNU libc installed.
|
||||
#
|
||||
# NOTE: The valgrind false positive problem could also potentially be solved
|
||||
# with valgrind suppression files but that kind of approach may be fragile.
|
||||
FROM ubuntu:18.04 as cpputest-build
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt install -y \
|
||||
automake \
|
||||
autoconf \
|
||||
cmake \
|
||||
curl \
|
||||
g++ \
|
||||
gcc \
|
||||
libtool \
|
||||
make \
|
||||
pkg-config \
|
||||
valgrind \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Cpputest built-in memory checks generate false positives in valgrind.
|
||||
# This is solved by compiling cpputest with memory checking disabled.
|
||||
WORKDIR /cpputest
|
||||
RUN curl -L https://github.com/cpputest/cpputest/releases/download/v3.8/cpputest-3.8.tar.gz | \
|
||||
tar --strip-components=1 -xzf -
|
||||
WORKDIR /cpputest/builddir
|
||||
RUN cmake -DMEMORY_LEAK_DETECTION=OFF .. && \
|
||||
make install
|
||||
|
||||
COPY ./redismodule /redismodule
|
||||
WORKDIR /redismodule
|
||||
RUN ./autogen.sh && \
|
||||
./configure
|
||||
#&& make test
|
||||
|
||||
|
||||
FROM nexus3.o-ran-sc.org:10004/o-ran-sc/bldr-alpine3-go:6-a3.11-rmr3 as build-env
|
||||
|
||||
RUN apk add cpputest
|
||||
COPY ./redismodule /redismodule
|
||||
WORKDIR /redismodule
|
||||
RUN ./autogen.sh && \
|
||||
./configure --disable-unit-test-memcheck && \
|
||||
# make test && \
|
||||
make install
|
||||
|
||||
FROM redis:5.0.5-alpine3.9
|
||||
|
||||
RUN apk add curl
|
||||
COPY --from=build-env /usr/local/libexec/redismodule/libredismodule.so /usr/local/libexec/redismodule/libredismodule.so
|
||||
WORKDIR /data
|
||||
|
||||
#ENTRYPOINT ["sh", "/usr/local/bin/docker-entrypoint.sh"]
|
||||
ENTRYPOINT ["redis-server"]
|
44
setup/dbaas/docker/Dockerfile.testapp
Normal file
44
setup/dbaas/docker/Dockerfile.testapp
Normal file
@@ -0,0 +1,44 @@
|
||||
# Copyright (c) 2019 AT&T Intellectual Property.
|
||||
# Copyright (c) 2019 Nokia.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
# platform project (RICP).
|
||||
#
|
||||
|
||||
FROM ubuntu:latest
|
||||
|
||||
# Install redis tools & golang & git
|
||||
RUN apt-get update && \
|
||||
apt install -y redis-tools && \
|
||||
apt install -y git && \
|
||||
apt install -y wget && \
|
||||
wget https://dl.google.com/go/go1.11.4.linux-amd64.tar.gz && \
|
||||
tar -xvf go1.11.4.linux-amd64.tar.gz && \
|
||||
mv go /usr/local && \
|
||||
apt-get clean
|
||||
|
||||
# Copy sourcefiles
|
||||
COPY ./testapplication ./testapplication
|
||||
|
||||
# Install go testapplication
|
||||
RUN export GOROOT=/usr/local/go && \
|
||||
export GOPATH=$HOME/Projects/Proj1 && \
|
||||
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH && \
|
||||
go get github.com/go-redis/redis && \
|
||||
go build /testapplication/go/testapp.go
|
||||
|
||||
# Keep the container alive
|
||||
ENTRYPOINT ["tail", "-f", "/dev/null"]
|
BIN
setup/dbaas/docs/_static/logo.png
vendored
Normal file
BIN
setup/dbaas/docs/_static/logo.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
6
setup/dbaas/docs/conf.py
Normal file
6
setup/dbaas/docs/conf.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from docs_conf.conf import *
|
||||
linkcheck_ignore = [
|
||||
'http://localhost.*',
|
||||
'http://127.0.0.1.*',
|
||||
'https://gerrit.o-ran-sc.org.*'
|
||||
]
|
3
setup/dbaas/docs/conf.yaml
Normal file
3
setup/dbaas/docs/conf.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
project_cfg: oran
|
||||
project: ric-plt/dbaas
|
BIN
setup/dbaas/docs/favicon.ico
Normal file
BIN
setup/dbaas/docs/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
31
setup/dbaas/docs/index.rst
Normal file
31
setup/dbaas/docs/index.rst
Normal file
@@ -0,0 +1,31 @@
|
||||
..
|
||||
.. Copyright (c) 2019 AT&T Intellectual Property.
|
||||
.. Copyright (c) 2019 Nokia.
|
||||
..
|
||||
.. Licensed under the Creative Commons Attribution 4.0 International
|
||||
.. Public License (the "License"); you may not use this file except
|
||||
.. in compliance with the License. You may obtain a copy of the License at
|
||||
..
|
||||
.. https://creativecommons.org/licenses/by/4.0/
|
||||
..
|
||||
.. Unless required by applicable law or agreed to in writing, documentation
|
||||
.. distributed under the License is distributed on an "AS IS" BASIS,
|
||||
.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
..
|
||||
.. See the License for the specific language governing permissions and
|
||||
.. limitations under the License.
|
||||
..
|
||||
|
||||
Welcome to O-RAN DBAAS Documentation
|
||||
====================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
overview.rst
|
||||
release-notes.rst
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
28
setup/dbaas/docs/overview.rst
Normal file
28
setup/dbaas/docs/overview.rst
Normal file
@@ -0,0 +1,28 @@
|
||||
..
|
||||
.. Copyright (c) 2019 AT&T Intellectual Property.
|
||||
.. Copyright (c) 2019 Nokia.
|
||||
..
|
||||
.. Licensed under the Creative Commons Attribution 4.0 International
|
||||
.. Public License (the "License"); you may not use this file except
|
||||
.. in compliance with the License. You may obtain a copy of the License at
|
||||
..
|
||||
.. https://creativecommons.org/licenses/by/4.0/
|
||||
..
|
||||
.. Unless required by applicable law or agreed to in writing, documentation
|
||||
.. distributed under the License is distributed on an "AS IS" BASIS,
|
||||
.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
..
|
||||
.. See the License for the specific language governing permissions and
|
||||
.. limitations under the License.
|
||||
..
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The ric-plt/dbaas repo provides all the needed elements to deploy database as
|
||||
a service (Dbaas) to kubernetes. Dbaas service is realized with a single
|
||||
container running Redis database. The database is configured to be
|
||||
non-persistent and non-redundant.
|
||||
|
||||
For the time being Dbaas only allowed usage is to provide database backend
|
||||
service for Shared Data Layer (SDL).
|
75
setup/dbaas/docs/release-notes.rst
Normal file
75
setup/dbaas/docs/release-notes.rst
Normal file
@@ -0,0 +1,75 @@
|
||||
..
|
||||
.. Copyright (c) 2019 AT&T Intellectual Property.
|
||||
.. Copyright (c) 2019 Nokia.
|
||||
..
|
||||
.. Licensed under the Creative Commons Attribution 4.0 International
|
||||
.. Public License (the "License"); you may not use this file except
|
||||
.. in compliance with the License. You may obtain a copy of the License at
|
||||
..
|
||||
.. https://creativecommons.org/licenses/by/4.0/
|
||||
..
|
||||
.. Unless required by applicable law or agreed to in writing, documentation
|
||||
.. distributed under the License is distributed on an "AS IS" BASIS,
|
||||
.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
..
|
||||
.. See the License for the specific language governing permissions and
|
||||
.. limitations under the License.
|
||||
..
|
||||
|
||||
Release-Notes
|
||||
=============
|
||||
|
||||
This document provides the release notes of the dbaas.
|
||||
|
||||
.. contents::
|
||||
:depth: 3
|
||||
:local:
|
||||
|
||||
|
||||
|
||||
Version history
|
||||
---------------
|
||||
|
||||
[0.4.1] - 2020-06-17
|
||||
|
||||
* Upgrade base image to bldr-alpine3:12-a3.11 in Redis docker build
|
||||
|
||||
[0.4.0] - 2020-04-23
|
||||
|
||||
* Bump version to 0.4.0 to follow RIC versioning rules (4 is meaning RIC release R4). No functional changes.
|
||||
|
||||
[0.3.2] - 2020-04-22
|
||||
|
||||
* Upgrade base image to bldr-alpine3:10-a3.22-rmr3 in Redis docker build
|
||||
* Fix redismodule resource leak
|
||||
|
||||
[0.3.1] - 2020-02-13
|
||||
|
||||
* Upgrade base image to alpine3-go:1-rmr1.13.1 in Redis docker build
|
||||
|
||||
[0.3.0] - 2020-01-23
|
||||
|
||||
* Enable unit tests and valgrind in CI.
|
||||
* Update redismodule with new commands.
|
||||
* Update documentation.
|
||||
|
||||
[0.2.2] - 2019-11-12
|
||||
|
||||
* Take Alpine (version 6-a3.9) linux base image into use in Redis docker image.
|
||||
* Add mandatory documentation files.
|
||||
|
||||
[0.2.1] - 2019-09-17
|
||||
|
||||
* Add the curl tool to docker image to facilitate trouble-shooting.
|
||||
|
||||
[0.2.0] - 2019-09-03
|
||||
|
||||
* Take Redis 5.0 in use.
|
||||
|
||||
[0.1.0] - 2019-06-17
|
||||
|
||||
* Initial Implementation to provide all the needed elements to deploy database
|
||||
as a service docker image to kubernetes.
|
||||
* Introduce new Redis modules: SETIE, SETNE, DELIE, DELNE, MSETPUB, MSETMPUB,
|
||||
SETXXPUB, SETNXPUB, SETIEPUB, SETNEPUB, DELPUB, DELMPUB, DELIEPUB, DELNEPUB,
|
||||
NGET, NDEL.
|
5
setup/dbaas/docs/requirements-docs.txt
Normal file
5
setup/dbaas/docs/requirements-docs.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
sphinx
|
||||
sphinx-rtd-theme
|
||||
sphinxcontrib-httpdomain
|
||||
recommonmark
|
||||
lfdocs-conf
|
134
setup/dbaas/redismodule/Makefile.am
Executable file
134
setup/dbaas/redismodule/Makefile.am
Executable file
@@ -0,0 +1,134 @@
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
redismoduledir = @libexecdir@/$(PACKAGE)
|
||||
redismodule_LTLIBRARIES = libredismodule.la
|
||||
#lib_LTLIBRARIES = libredismodule.la
|
||||
|
||||
BASE_LDFLAGS =
|
||||
|
||||
libredismodule_la_SOURCES = \
|
||||
include/redismodule.h\
|
||||
src/exstrings.c
|
||||
|
||||
libredismodule_la_CFLAGS = \
|
||||
-std=c11 -fPIC -g -Wall -Werror -Wextra \
|
||||
-DREDISMODULE_EXPERIMENTAL_API \
|
||||
-I${includedir} -I${top_srcdir}/include
|
||||
|
||||
|
||||
libredismodule_la_LDFLAGS = $(BASE_LDFLAGS) -avoid-version -module -shared
|
||||
|
||||
#pkgincludedir = ${includedir}
|
||||
#pkginclude_HEADERS = include/redismodule.h
|
||||
|
||||
clean-local:
|
||||
rm -rf ${builddir}/libredismodule.pc
|
||||
|
||||
if UNIT_TEST_ENABLED
|
||||
# UT
|
||||
CPP_U_TEST=$(CPP_U_TEST_LATEST)
|
||||
check_PROGRAMS = redismodule_ut redismodule_ut2
|
||||
#TESTS = ${check_PROGRAMS}
|
||||
redismodule_ut_SOURCES = \
|
||||
src/exstrings.c \
|
||||
tst/mock/include/commonStub.h \
|
||||
tst/mock/include/exstringsStub.h \
|
||||
tst/mock/include/redismodule.h \
|
||||
tst/mock/src/commonStub.cpp \
|
||||
tst/mock/src/redismoduleStub.cpp \
|
||||
tst/src/exstrings_test.cpp \
|
||||
tst/src/main.cpp
|
||||
|
||||
|
||||
redismodule_ut_CFLAGS = \
|
||||
-std=c11 -g -Wall \
|
||||
-fprofile-arcs -ftest-coverage \
|
||||
-D__UT__ \
|
||||
$(LIBCPPUTEST_CFLAGS) \
|
||||
-I${top_srcdir}/tst/mock/include \
|
||||
-I${includedir} \
|
||||
-I${top_srcdir}/include \
|
||||
-I${CPP_U_TEST_LATEST}/include \
|
||||
-Wall -Werror -Wextra
|
||||
|
||||
redismodule_ut_CXXFLAGS = \
|
||||
-std=c++11 -g -Wall \
|
||||
-fprofile-arcs -ftest-coverage \
|
||||
-D__UT__ \
|
||||
$(LIBCPPUTEST_CFLAGS) \
|
||||
-I${top_srcdir}/tst/mock/include \
|
||||
-I${includedir} \
|
||||
-I${top_srcdir}/include \
|
||||
-I${CPP_U_TEST_LATEST}/include \
|
||||
-Wall -Werror -Wextra
|
||||
|
||||
|
||||
redismodule_ut_LDFLAGS = -Wl,-rpath=${libdir} ${UT_COVERAGE_LDFLAGS}
|
||||
redismodule_ut_LDADD = -L${libdir} $(LIBCPPUTEST_LIBS) -lgcov
|
||||
|
||||
|
||||
redismodule_ut2_SOURCES = \
|
||||
src/exstrings.c \
|
||||
tst/include/ut_helpers.hpp \
|
||||
tst/mock/include/commonStub.h \
|
||||
tst/mock/include/exstringsStub.h \
|
||||
tst/mock/include/redismodule.h \
|
||||
tst/mock/src/commonStub.cpp \
|
||||
tst/mock/src/redismoduleNewStub.cpp \
|
||||
tst/src/exstrings_ndel_test.cpp \
|
||||
tst/src/exstrings_nget_test.cpp \
|
||||
tst/src/main.cpp \
|
||||
tst/src/ut_helpers.cpp
|
||||
|
||||
|
||||
redismodule_ut2_CFLAGS = \
|
||||
-std=c11 -g -Wall \
|
||||
-fprofile-arcs -ftest-coverage \
|
||||
-D__UT__ \
|
||||
$(LIBCPPUTEST_CFLAGS) \
|
||||
-I${top_srcdir}/tst/mock/include \
|
||||
-I${includedir} \
|
||||
-I${top_srcdir}/include \
|
||||
-I${CPP_U_TEST_LATEST}/include \
|
||||
-Wall -Werror -Wextra
|
||||
|
||||
redismodule_ut2_CXXFLAGS = \
|
||||
-std=c++11 -g -Wall \
|
||||
-fprofile-arcs -ftest-coverage \
|
||||
-D__UT__ \
|
||||
$(LIBCPPUTEST_CFLAGS) \
|
||||
-I${top_srcdir}/tst/mock/include \
|
||||
-I${top_srcdir}/tst/include \
|
||||
-I${includedir} \
|
||||
-I${top_srcdir}/include \
|
||||
-I${CPP_U_TEST_LATEST}/include \
|
||||
-Wall -Werror -Wextra
|
||||
|
||||
|
||||
redismodule_ut2_LDFLAGS = -Wl,-rpath=${libdir} ${UT_COVERAGE_LDFLAGS}
|
||||
redismodule_ut2_LDADD = -L${libdir} $(LIBCPPUTEST_LIBS) -lgcov
|
||||
|
||||
|
||||
if UNIT_TEST_MEMCHECK_ENABLED
|
||||
test: ut_memcheck_test
|
||||
else
|
||||
test: ut_test
|
||||
endif
|
||||
|
||||
ut_test: redismodule_ut redismodule_ut2
|
||||
./redismodule_ut
|
||||
./redismodule_ut2
|
||||
|
||||
ut_memcheck_test: redismodule_ut redismodule_ut2
|
||||
valgrind --error-exitcode=1 --leak-check=full ./redismodule_ut
|
||||
valgrind --error-exitcode=1 --leak-check=full ./redismodule_ut2
|
||||
|
||||
TESTS = run-tests.sh
|
||||
|
||||
else
|
||||
|
||||
test:
|
||||
echo 'enable ut with configure flag: --enable-unit-test and valgrind memcheck with: --enable-unit-test-memcheck'
|
||||
exit 1
|
||||
|
||||
endif #UNIT_TEST_ENABLED
|
260
setup/dbaas/redismodule/README.md
Executable file
260
setup/dbaas/redismodule/README.md
Executable file
@@ -0,0 +1,260 @@
|
||||
# Introduction
|
||||
|
||||
This subdirectory provides implementation for the commands which are implemented
|
||||
as a [Redis modules](https://redis.io/topics/modules-intro).
|
||||
|
||||
# Compiling and Unit Tests
|
||||
|
||||
To compile, run unit tests and install use the commands:
|
||||
```
|
||||
./autogen.sh
|
||||
./configure
|
||||
make
|
||||
make test
|
||||
make install
|
||||
```
|
||||
|
||||
By default unit tests and valgrind memory checking are enabled.
|
||||
This requires `cpputest` and `valgrind` as additional dependencies.
|
||||
Unit test memory checking can be disabled with the `configure` option
|
||||
`--disable-unit-test-memcheck` and the unit tests can be completely disabled
|
||||
with the `configure` option `--disable-unit-test`.
|
||||
For example to compile and install with unit tests completely disabled
|
||||
one would run the commands:
|
||||
```
|
||||
./autogen.sh
|
||||
./configure --disable-unit-test
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
# Commands
|
||||
|
||||
## SETIE key value oldvalue [expiration EX seconds|PX milliseconds]
|
||||
|
||||
Time complexity: O(1) + O(1)
|
||||
|
||||
Checks a String 'key' for 'oldvalue' equality and set key for 'value' with
|
||||
optional expired.
|
||||
|
||||
```
|
||||
Example:
|
||||
|
||||
redis> get mykey
|
||||
(nil)
|
||||
redis> setie mykey "Hello again" "Hello"
|
||||
(nil)
|
||||
|
||||
redis> set mykey "Hello"
|
||||
OK
|
||||
redis> get mykey
|
||||
"Hello"
|
||||
redis> setie mykey "Hello again" "Hello"
|
||||
"OK"
|
||||
redis> get mykey
|
||||
"Hello again"
|
||||
redis> setie mykey "Hello 2" "Hello"
|
||||
(nil)
|
||||
redis> get mykey
|
||||
"Hello again"
|
||||
redis> setie mykey "Hello 2" "Hello again" ex 100
|
||||
"OK"
|
||||
redis> ttl mykey
|
||||
(integer) 96
|
||||
redis> get mykey
|
||||
"Hello 2"
|
||||
```
|
||||
|
||||
## SETNE key value oldvalue [expiration EX seconds|PX milliseconds]
|
||||
|
||||
Time complexity: O(1) + O(1)
|
||||
|
||||
Checks a String 'key' for 'oldvalue' not equality and set key for 'value' with optional expired.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
redis> get mykey
|
||||
(nil)
|
||||
redis> setne mykey "Hello again" "Hello"
|
||||
"OK"
|
||||
redis> get mykey
|
||||
"Hello again"
|
||||
redis> setne mykey "Hello 2" "Hello again"
|
||||
(nil)
|
||||
redis> setne mykey "Hello 2" "Hello"
|
||||
"OK"
|
||||
redis> get mykey
|
||||
"Hello 2"
|
||||
redis> setne mykey "Hello 3" "Hello" ex 100
|
||||
"OK"
|
||||
redis> get mykey
|
||||
"Hello 3"
|
||||
redis> ttl mykey
|
||||
(integer) 93
|
||||
```
|
||||
|
||||
## DELIE key oldvalue
|
||||
|
||||
Time complexity: O(1) + O(1)
|
||||
|
||||
Checks a String 'key' for 'oldvalue' equality and delete the key.
|
||||
|
||||
```
|
||||
Example:
|
||||
redis> get mykey
|
||||
(nil)
|
||||
redis> set mykey "Hello"
|
||||
"OK"
|
||||
redis> get mykey
|
||||
"Hello"
|
||||
redis> delie mykey "Hello again"
|
||||
(integer) 0
|
||||
redis> get mykey
|
||||
"Hello"
|
||||
redis> delie mykey "Hello"
|
||||
(integer) 1
|
||||
redis> get mykey
|
||||
(nil)
|
||||
```
|
||||
|
||||
## DELNE key oldvalue
|
||||
|
||||
Time complexity: O(1) + O(1)
|
||||
|
||||
Checks a String 'key' for 'oldvalue' not equality and delete the key.
|
||||
|
||||
```
|
||||
Example:
|
||||
redis> get mykey
|
||||
(nil)
|
||||
redis> set mykey "Hello"
|
||||
"OK"
|
||||
redis> get mykey
|
||||
"Hello"
|
||||
redis> delne mykey "Hello"
|
||||
(integer) 0
|
||||
redis> get mykey
|
||||
"Hello"
|
||||
redis> delne mykey "Hello again"
|
||||
(integer) 1
|
||||
redis> get mykey
|
||||
(nil)
|
||||
```
|
||||
|
||||
## MSETPUB key value [key value...] channel message
|
||||
|
||||
Time complexity: O(N) where N is the number of keys to set + O(N+M) where N is the number of clients subscribed to the receiving channel and M is the total number of subscribed patterns (by any client)
|
||||
|
||||
Set the given keys to their respective values and post a message to the given channel
|
||||
|
||||
## MSETMPUB number_of_key_value_pairs number_of_channel_message_pairs key value [ key value ... ] channel message [ channel message ... ]
|
||||
|
||||
Time complexity: O(N) where N is the number of keys to set + O(N_1+M) [ + O(N_2+M) + ... ] where N_i are the number of clients subscribed to the corresponding receiving channel and M is the total number of subscribed patterns (by any client)
|
||||
|
||||
Set the given keys to their respective values and post messages to their respective channels
|
||||
|
||||
## SETXXPUB key value channel message [channel message...]
|
||||
|
||||
Time complexity: O(1) + O(1) + O(N_1+M) [ + O(N_2+M) + ... ] where N_i are the number of clients subscribed to the receiving channel and M is the total number of subscribed patterns (by any client).
|
||||
|
||||
Set key to hold string value if key already exists and post given messages to the corresponding channels if key value was set successfully
|
||||
|
||||
## SETNXPUB key value channel message [channel message...]
|
||||
|
||||
Time complexity: O(1) + O(1) + O(N_1+M) [ + O(N_2+M) + ... ] where N_i are the number of clients subscribed to the receiving channel and M is the total number of subscribed patterns (by any client).
|
||||
|
||||
Set key to hold string value if key does not exist and post given messages to the corresponding channels if key value was set successfully
|
||||
|
||||
## SETIEPUB key value oldvalue channel message [channel message...]
|
||||
|
||||
Time complexity: O(1) + O(1) + O(1) + O(N_1+M) [ + O(N_2+M) + ... ] where N_i are the number of clients subscribed to the receiving channel and M is the total number of subscribed patterns (by any client).
|
||||
|
||||
If the string corresponding to 'key' is equal to 'oldvalue' then set key for 'value' and post given messages to the corresponding channels if key value was set successfully
|
||||
|
||||
## SETNEPUB key value oldvalue channel message [channel message...]
|
||||
|
||||
Time complexity: O(1) + O(1) + O(1) + O(N_1+M) [ + O(N_2+M) + ... ] where N_i are the number of clients subscribed to the receiving channel and M is the total number of subscribed patterns (by any client).
|
||||
|
||||
If the string corresponding to 'key' is not equal to 'oldvalue' then set key for 'value' and post given messages to the corresponding channels if key value was set successfully
|
||||
|
||||
## DELPUB key [key...] channel message
|
||||
|
||||
Time complexity: O(N) where N is the number of keys that will be removed + O(N+M) where N is the number of clients subscribed to the receiving channel and M is the total number of subscribed patterns (by any client)
|
||||
|
||||
Removes the specified keys and post a message to the given channel if delete key successfully(return >0)
|
||||
|
||||
## DELMPUB number_of_keys number_of_channel_message_pairs key [ key ... ] channel message [ channel message ... ]
|
||||
|
||||
Time complexity: O(N) where N is the number of keys that will be removed + O(N_1+M) [ + O(N_2+M) + ... ] where N_i are the number of clients subscribed to the receiving channel and M is the total number of subscribed patterns (by any client)
|
||||
|
||||
Remove the specified keys. If any of the keys was deleted succesfully (delete return value > 0) then post given messages to the corresponding channels.
|
||||
|
||||
## DELIEPUB key oldvalue channel message [channel message...]
|
||||
|
||||
Time complexity: O(1) + O(1) + O(1) + O(N_1+M) [ + O(N_2+M) + ...] where N_i are the number of clients subscribed to the corrensponding receiving channel and M is the total number of subscribed patterns (by any client)
|
||||
|
||||
If the string corresponding to 'key' is equal to 'oldvalue' then delete the key. If deletion was succesful (delete return value was 1) then post given messages to the corresponding channels.
|
||||
|
||||
## DELNEPUB key oldvalue channel message [channel message...]
|
||||
|
||||
Time complexity: O(1) + O(1) + O(1) + O(N_1+M) [ + O(N_2+M) + ...] where N_i are the number of clients subscribed to the corrensponding receiving channel and M is the total number of subscribed patterns (by any client)
|
||||
|
||||
If the string corresponding to 'key' is not equal to 'oldvalue' then delete the key. If deletion was succesful (delete return value was 1) then post given messages to the corresponding channels.
|
||||
|
||||
## NGET pattern
|
||||
|
||||
Time complexity: O(N) with N being the number of keys in the instance + O(N) where N is the number of keys to retrieve
|
||||
|
||||
Returns all key-value pairs matching pattern.
|
||||
|
||||
```
|
||||
example:
|
||||
|
||||
redis> nget mykey*
|
||||
(empty list or set)
|
||||
|
||||
redis> set mykey1 "myvalue1"
|
||||
OK
|
||||
redis> set mykey2 "myvalue2"
|
||||
OK
|
||||
redis> set mykey3 "myvalue3"
|
||||
OK
|
||||
redis> set mykey4 "myvalue4"
|
||||
OK
|
||||
redis> nget mykey*
|
||||
1) "mykey2"
|
||||
2) "myvalue2"
|
||||
3) "mykey1"
|
||||
4) "myvalue1"
|
||||
5) "mykey4"
|
||||
6) "myvalue4"
|
||||
7) "mykey3"
|
||||
8) "myvalue3"
|
||||
```
|
||||
|
||||
## NDEL pattern
|
||||
|
||||
Time complexity: O(N) with N being the number of keys in the instance + O(N) where N is the number of keys that will be removed
|
||||
|
||||
Remove all key-value pairs matching pattern.
|
||||
|
||||
```
|
||||
example:
|
||||
|
||||
redis> nget mykey*
|
||||
1) "mykey2"
|
||||
2) "myvalue2"
|
||||
3) "mykey1"
|
||||
4) "myvalue1"
|
||||
5) "mykey4"
|
||||
6) "myvalue4"
|
||||
7) "mykey3"
|
||||
8) "myvalue3"
|
||||
|
||||
redis> ndel mykey*
|
||||
(integer) 4
|
||||
|
||||
redis> ndel mykey*
|
||||
(integer) 0
|
||||
```
|
3
setup/dbaas/redismodule/autogen.sh
Executable file
3
setup/dbaas/redismodule/autogen.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
autoreconf --install
|
54
setup/dbaas/redismodule/configure.ac
Executable file
54
setup/dbaas/redismodule/configure.ac
Executable file
@@ -0,0 +1,54 @@
|
||||
AC_INIT([redismodule], [0.0.0], [], [], [https://gerrit.oran-osc.org/r/#/admin/projects/ric-plt/dbaas])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_MACRO_DIRS([m4])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects tar-pax])
|
||||
|
||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||
LT_INIT([disable-static])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_MAKE_SET
|
||||
|
||||
AC_ARG_ENABLE([unit-test],
|
||||
[--disable-unit-test], [Disable unit tests]
|
||||
)
|
||||
|
||||
AS_IF([test x"$enable_unit_test" != x"no"],
|
||||
[
|
||||
PKG_CHECK_MODULES([LIBCPPUTEST],[cpputest])
|
||||
AM_CONDITIONAL([UNIT_TEST_ENABLED], [true])
|
||||
],
|
||||
[
|
||||
AM_CONDITIONAL([UNIT_TEST_ENABLED], [false])
|
||||
]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([unit-test-memcheck],
|
||||
[AS_HELP_STRING([--disable-unit-test-memcheck], [Do not run unit tests with valgrind])]
|
||||
)
|
||||
|
||||
AS_IF([test x"$enable_unit_test_memcheck" != x"no"],
|
||||
[
|
||||
AC_CHECK_PROG(VALGRIND_CHECK, valgrind, yes)
|
||||
AM_CONDITIONAL([UNIT_TEST_MEMCHECK_ENABLED], [true])
|
||||
],
|
||||
[
|
||||
AM_CONDITIONAL([UNIT_TEST_MEMCHECK_ENABLED], [false])
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
# Checks for header files.
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_HEADER_STDBOOL
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
|
||||
AC_OUTPUT
|
574
setup/dbaas/redismodule/include/redismodule.h
Executable file
574
setup/dbaas/redismodule/include/redismodule.h
Executable file
@@ -0,0 +1,574 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Nokia.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
* platform project (RICP).
|
||||
*/
|
||||
|
||||
#ifndef REDISMODULE_H
|
||||
#define REDISMODULE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* ---------------- Defines common between core and modules --------------- */
|
||||
|
||||
/* Error status return values. */
|
||||
#define REDISMODULE_OK 0
|
||||
#define REDISMODULE_ERR 1
|
||||
|
||||
/* API versions. */
|
||||
#define REDISMODULE_APIVER_1 1
|
||||
|
||||
/* API flags and constants */
|
||||
#define REDISMODULE_READ (1<<0)
|
||||
#define REDISMODULE_WRITE (1<<1)
|
||||
|
||||
#define REDISMODULE_LIST_HEAD 0
|
||||
#define REDISMODULE_LIST_TAIL 1
|
||||
|
||||
/* Key types. */
|
||||
#define REDISMODULE_KEYTYPE_EMPTY 0
|
||||
#define REDISMODULE_KEYTYPE_STRING 1
|
||||
#define REDISMODULE_KEYTYPE_LIST 2
|
||||
#define REDISMODULE_KEYTYPE_HASH 3
|
||||
#define REDISMODULE_KEYTYPE_SET 4
|
||||
#define REDISMODULE_KEYTYPE_ZSET 5
|
||||
#define REDISMODULE_KEYTYPE_MODULE 6
|
||||
|
||||
/* Reply types. */
|
||||
#define REDISMODULE_REPLY_UNKNOWN -1
|
||||
#define REDISMODULE_REPLY_STRING 0
|
||||
#define REDISMODULE_REPLY_ERROR 1
|
||||
#define REDISMODULE_REPLY_INTEGER 2
|
||||
#define REDISMODULE_REPLY_ARRAY 3
|
||||
#define REDISMODULE_REPLY_NULL 4
|
||||
|
||||
/* Postponed array length. */
|
||||
#define REDISMODULE_POSTPONED_ARRAY_LEN -1
|
||||
|
||||
/* Expire */
|
||||
#define REDISMODULE_NO_EXPIRE -1
|
||||
|
||||
/* Sorted set API flags. */
|
||||
#define REDISMODULE_ZADD_XX (1<<0)
|
||||
#define REDISMODULE_ZADD_NX (1<<1)
|
||||
#define REDISMODULE_ZADD_ADDED (1<<2)
|
||||
#define REDISMODULE_ZADD_UPDATED (1<<3)
|
||||
#define REDISMODULE_ZADD_NOP (1<<4)
|
||||
|
||||
/* Hash API flags. */
|
||||
#define REDISMODULE_HASH_NONE 0
|
||||
#define REDISMODULE_HASH_NX (1<<0)
|
||||
#define REDISMODULE_HASH_XX (1<<1)
|
||||
#define REDISMODULE_HASH_CFIELDS (1<<2)
|
||||
#define REDISMODULE_HASH_EXISTS (1<<3)
|
||||
|
||||
/* Context Flags: Info about the current context returned by
|
||||
* RM_GetContextFlags(). */
|
||||
|
||||
/* The command is running in the context of a Lua script */
|
||||
#define REDISMODULE_CTX_FLAGS_LUA (1<<0)
|
||||
/* The command is running inside a Redis transaction */
|
||||
#define REDISMODULE_CTX_FLAGS_MULTI (1<<1)
|
||||
/* The instance is a master */
|
||||
#define REDISMODULE_CTX_FLAGS_MASTER (1<<2)
|
||||
/* The instance is a slave */
|
||||
#define REDISMODULE_CTX_FLAGS_SLAVE (1<<3)
|
||||
/* The instance is read-only (usually meaning it's a slave as well) */
|
||||
#define REDISMODULE_CTX_FLAGS_READONLY (1<<4)
|
||||
/* The instance is running in cluster mode */
|
||||
#define REDISMODULE_CTX_FLAGS_CLUSTER (1<<5)
|
||||
/* The instance has AOF enabled */
|
||||
#define REDISMODULE_CTX_FLAGS_AOF (1<<6)
|
||||
/* The instance has RDB enabled */
|
||||
#define REDISMODULE_CTX_FLAGS_RDB (1<<7)
|
||||
/* The instance has Maxmemory set */
|
||||
#define REDISMODULE_CTX_FLAGS_MAXMEMORY (1<<8)
|
||||
/* Maxmemory is set and has an eviction policy that may delete keys */
|
||||
#define REDISMODULE_CTX_FLAGS_EVICT (1<<9)
|
||||
/* Redis is out of memory according to the maxmemory flag. */
|
||||
#define REDISMODULE_CTX_FLAGS_OOM (1<<10)
|
||||
/* Less than 25% of memory available according to maxmemory. */
|
||||
#define REDISMODULE_CTX_FLAGS_OOM_WARNING (1<<11)
|
||||
/* The command was sent over the replication link. */
|
||||
#define REDISMODULE_CTX_FLAGS_REPLICATED (1<<12)
|
||||
/* Redis is currently loading either from AOF or RDB. */
|
||||
#define REDISMODULE_CTX_FLAGS_LOADING (1<<13)
|
||||
|
||||
|
||||
#define REDISMODULE_NOTIFY_GENERIC (1<<2) /* g */
|
||||
#define REDISMODULE_NOTIFY_STRING (1<<3) /* $ */
|
||||
#define REDISMODULE_NOTIFY_LIST (1<<4) /* l */
|
||||
#define REDISMODULE_NOTIFY_SET (1<<5) /* s */
|
||||
#define REDISMODULE_NOTIFY_HASH (1<<6) /* h */
|
||||
#define REDISMODULE_NOTIFY_ZSET (1<<7) /* z */
|
||||
#define REDISMODULE_NOTIFY_EXPIRED (1<<8) /* x */
|
||||
#define REDISMODULE_NOTIFY_EVICTED (1<<9) /* e */
|
||||
#define REDISMODULE_NOTIFY_STREAM (1<<10) /* t */
|
||||
#define REDISMODULE_NOTIFY_ALL (REDISMODULE_NOTIFY_GENERIC | REDISMODULE_NOTIFY_STRING | REDISMODULE_NOTIFY_LIST | REDISMODULE_NOTIFY_SET | REDISMODULE_NOTIFY_HASH | REDISMODULE_NOTIFY_ZSET | REDISMODULE_NOTIFY_EXPIRED | REDISMODULE_NOTIFY_EVICTED | REDISMODULE_NOTIFY_STREAM) /* A */
|
||||
|
||||
|
||||
/* A special pointer that we can use between the core and the module to signal
|
||||
* field deletion, and that is impossible to be a valid pointer. */
|
||||
#define REDISMODULE_HASH_DELETE ((RedisModuleString*)(long)1)
|
||||
|
||||
/* Error messages. */
|
||||
#define REDISMODULE_ERRORMSG_WRONGTYPE "WRONGTYPE Operation against a key holding the wrong kind of value"
|
||||
|
||||
#define REDISMODULE_POSITIVE_INFINITE (1.0/0.0)
|
||||
#define REDISMODULE_NEGATIVE_INFINITE (-1.0/0.0)
|
||||
|
||||
/* Cluster API defines. */
|
||||
#define REDISMODULE_NODE_ID_LEN 40
|
||||
#define REDISMODULE_NODE_MYSELF (1<<0)
|
||||
#define REDISMODULE_NODE_MASTER (1<<1)
|
||||
#define REDISMODULE_NODE_SLAVE (1<<2)
|
||||
#define REDISMODULE_NODE_PFAIL (1<<3)
|
||||
#define REDISMODULE_NODE_FAIL (1<<4)
|
||||
#define REDISMODULE_NODE_NOFAILOVER (1<<5)
|
||||
|
||||
#define REDISMODULE_CLUSTER_FLAG_NONE 0
|
||||
#define REDISMODULE_CLUSTER_FLAG_NO_FAILOVER (1<<1)
|
||||
#define REDISMODULE_CLUSTER_FLAG_NO_REDIRECTION (1<<2)
|
||||
|
||||
#define REDISMODULE_NOT_USED(V) ((void) V)
|
||||
|
||||
/* Bit flags for aux_save_triggers and the aux_load and aux_save callbacks */
|
||||
#define REDISMODULE_AUX_BEFORE_RDB (1<<0)
|
||||
#define REDISMODULE_AUX_AFTER_RDB (1<<1)
|
||||
|
||||
/* This type represents a timer handle, and is returned when a timer is
|
||||
* registered and used in order to invalidate a timer. It's just a 64 bit
|
||||
* number, because this is how each timer is represented inside the radix tree
|
||||
* of timers that are going to expire, sorted by expire time. */
|
||||
typedef uint64_t RedisModuleTimerID;
|
||||
|
||||
/* CommandFilter Flags */
|
||||
|
||||
/* Do filter RedisModule_Call() commands initiated by module itself. */
|
||||
#define REDISMODULE_CMDFILTER_NOSELF (1<<0)
|
||||
|
||||
/* ------------------------- End of common defines ------------------------ */
|
||||
|
||||
#ifndef REDISMODULE_CORE
|
||||
|
||||
typedef long long mstime_t;
|
||||
|
||||
/* Incomplete structures for compiler checks but opaque access. */
|
||||
typedef struct RedisModuleCtx RedisModuleCtx;
|
||||
typedef struct RedisModuleKey RedisModuleKey;
|
||||
typedef struct RedisModuleString RedisModuleString;
|
||||
typedef struct RedisModuleCallReply RedisModuleCallReply;
|
||||
typedef struct RedisModuleIO RedisModuleIO;
|
||||
typedef struct RedisModuleType RedisModuleType;
|
||||
typedef struct RedisModuleDigest RedisModuleDigest;
|
||||
typedef struct RedisModuleBlockedClient RedisModuleBlockedClient;
|
||||
typedef struct RedisModuleClusterInfo RedisModuleClusterInfo;
|
||||
typedef struct RedisModuleDict RedisModuleDict;
|
||||
typedef struct RedisModuleDictIter RedisModuleDictIter;
|
||||
typedef struct RedisModuleCommandFilterCtx RedisModuleCommandFilterCtx;
|
||||
typedef struct RedisModuleCommandFilter RedisModuleCommandFilter;
|
||||
|
||||
typedef int (*RedisModuleCmdFunc)(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
typedef void (*RedisModuleDisconnectFunc)(RedisModuleCtx *ctx, RedisModuleBlockedClient *bc);
|
||||
typedef int (*RedisModuleNotificationFunc)(RedisModuleCtx *ctx, int type, const char *event, RedisModuleString *key);
|
||||
typedef void *(*RedisModuleTypeLoadFunc)(RedisModuleIO *rdb, int encver);
|
||||
typedef void (*RedisModuleTypeSaveFunc)(RedisModuleIO *rdb, void *value);
|
||||
typedef int (*RedisModuleTypeAuxLoadFunc)(RedisModuleIO *rdb, int encver, int when);
|
||||
typedef void (*RedisModuleTypeAuxSaveFunc)(RedisModuleIO *rdb, int when);
|
||||
typedef void (*RedisModuleTypeRewriteFunc)(RedisModuleIO *aof, RedisModuleString *key, void *value);
|
||||
typedef size_t (*RedisModuleTypeMemUsageFunc)(const void *value);
|
||||
typedef void (*RedisModuleTypeDigestFunc)(RedisModuleDigest *digest, void *value);
|
||||
typedef void (*RedisModuleTypeFreeFunc)(void *value);
|
||||
typedef void (*RedisModuleClusterMessageReceiver)(RedisModuleCtx *ctx, const char *sender_id, uint8_t type, const unsigned char *payload, uint32_t len);
|
||||
typedef void (*RedisModuleTimerProc)(RedisModuleCtx *ctx, void *data);
|
||||
typedef void (*RedisModuleCommandFilterFunc) (RedisModuleCommandFilterCtx *filter);
|
||||
|
||||
#define REDISMODULE_TYPE_METHOD_VERSION 2
|
||||
typedef struct RedisModuleTypeMethods {
|
||||
uint64_t version;
|
||||
RedisModuleTypeLoadFunc rdb_load;
|
||||
RedisModuleTypeSaveFunc rdb_save;
|
||||
RedisModuleTypeRewriteFunc aof_rewrite;
|
||||
RedisModuleTypeMemUsageFunc mem_usage;
|
||||
RedisModuleTypeDigestFunc digest;
|
||||
RedisModuleTypeFreeFunc free;
|
||||
RedisModuleTypeAuxLoadFunc aux_load;
|
||||
RedisModuleTypeAuxSaveFunc aux_save;
|
||||
int aux_save_triggers;
|
||||
} RedisModuleTypeMethods;
|
||||
|
||||
#define REDISMODULE_GET_API(name) \
|
||||
RedisModule_GetApi("RedisModule_" #name, ((void **)&RedisModule_ ## name))
|
||||
|
||||
#define REDISMODULE_API_FUNC(x) (*x)
|
||||
|
||||
|
||||
void *REDISMODULE_API_FUNC(RedisModule_Alloc)(size_t bytes);
|
||||
void *REDISMODULE_API_FUNC(RedisModule_Realloc)(void *ptr, size_t bytes);
|
||||
void REDISMODULE_API_FUNC(RedisModule_Free)(void *ptr);
|
||||
void *REDISMODULE_API_FUNC(RedisModule_Calloc)(size_t nmemb, size_t size);
|
||||
char *REDISMODULE_API_FUNC(RedisModule_Strdup)(const char *str);
|
||||
int REDISMODULE_API_FUNC(RedisModule_GetApi)(const char *, void *);
|
||||
int REDISMODULE_API_FUNC(RedisModule_CreateCommand)(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep);
|
||||
void REDISMODULE_API_FUNC(RedisModule_SetModuleAttribs)(RedisModuleCtx *ctx, const char *name, int ver, int apiver);
|
||||
int REDISMODULE_API_FUNC(RedisModule_IsModuleNameBusy)(const char *name);
|
||||
int REDISMODULE_API_FUNC(RedisModule_WrongArity)(RedisModuleCtx *ctx);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithLongLong)(RedisModuleCtx *ctx, long long ll);
|
||||
int REDISMODULE_API_FUNC(RedisModule_GetSelectedDb)(RedisModuleCtx *ctx);
|
||||
int REDISMODULE_API_FUNC(RedisModule_SelectDb)(RedisModuleCtx *ctx, int newid);
|
||||
void *REDISMODULE_API_FUNC(RedisModule_OpenKey)(RedisModuleCtx *ctx, RedisModuleString *keyname, int mode);
|
||||
void REDISMODULE_API_FUNC(RedisModule_CloseKey)(RedisModuleKey *kp);
|
||||
int REDISMODULE_API_FUNC(RedisModule_KeyType)(RedisModuleKey *kp);
|
||||
size_t REDISMODULE_API_FUNC(RedisModule_ValueLength)(RedisModuleKey *kp);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ListPush)(RedisModuleKey *kp, int where, RedisModuleString *ele);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_ListPop)(RedisModuleKey *key, int where);
|
||||
RedisModuleCallReply *REDISMODULE_API_FUNC(RedisModule_Call)(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...);
|
||||
const char *REDISMODULE_API_FUNC(RedisModule_CallReplyProto)(RedisModuleCallReply *reply, size_t *len);
|
||||
void REDISMODULE_API_FUNC(RedisModule_FreeCallReply)(RedisModuleCallReply *reply);
|
||||
int REDISMODULE_API_FUNC(RedisModule_CallReplyType)(RedisModuleCallReply *reply);
|
||||
long long REDISMODULE_API_FUNC(RedisModule_CallReplyInteger)(RedisModuleCallReply *reply);
|
||||
size_t REDISMODULE_API_FUNC(RedisModule_CallReplyLength)(RedisModuleCallReply *reply);
|
||||
RedisModuleCallReply *REDISMODULE_API_FUNC(RedisModule_CallReplyArrayElement)(RedisModuleCallReply *reply, size_t idx);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CreateString)(RedisModuleCtx *ctx, const char *ptr, size_t len);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CreateStringFromLongLong)(RedisModuleCtx *ctx, long long ll);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CreateStringFromString)(RedisModuleCtx *ctx, const RedisModuleString *str);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CreateStringPrintf)(RedisModuleCtx *ctx, const char *fmt, ...);
|
||||
void REDISMODULE_API_FUNC(RedisModule_FreeString)(RedisModuleCtx *ctx, RedisModuleString *str);
|
||||
const char *REDISMODULE_API_FUNC(RedisModule_StringPtrLen)(const RedisModuleString *str, size_t *len);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithError)(RedisModuleCtx *ctx, const char *err);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithSimpleString)(RedisModuleCtx *ctx, const char *msg);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithArray)(RedisModuleCtx *ctx, long len);
|
||||
void REDISMODULE_API_FUNC(RedisModule_ReplySetArrayLength)(RedisModuleCtx *ctx, long len);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithStringBuffer)(RedisModuleCtx *ctx, const char *buf, size_t len);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithCString)(RedisModuleCtx *ctx, const char *buf);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithString)(RedisModuleCtx *ctx, RedisModuleString *str);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithNull)(RedisModuleCtx *ctx);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithDouble)(RedisModuleCtx *ctx, double d);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithCallReply)(RedisModuleCtx *ctx, RedisModuleCallReply *reply);
|
||||
int REDISMODULE_API_FUNC(RedisModule_StringToLongLong)(const RedisModuleString *str, long long *ll);
|
||||
int REDISMODULE_API_FUNC(RedisModule_StringToDouble)(const RedisModuleString *str, double *d);
|
||||
void REDISMODULE_API_FUNC(RedisModule_AutoMemory)(RedisModuleCtx *ctx);
|
||||
int REDISMODULE_API_FUNC(RedisModule_Replicate)(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplicateVerbatim)(RedisModuleCtx *ctx);
|
||||
const char *REDISMODULE_API_FUNC(RedisModule_CallReplyStringPtr)(RedisModuleCallReply *reply, size_t *len);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CreateStringFromCallReply)(RedisModuleCallReply *reply);
|
||||
int REDISMODULE_API_FUNC(RedisModule_DeleteKey)(RedisModuleKey *key);
|
||||
int REDISMODULE_API_FUNC(RedisModule_UnlinkKey)(RedisModuleKey *key);
|
||||
int REDISMODULE_API_FUNC(RedisModule_StringSet)(RedisModuleKey *key, RedisModuleString *str);
|
||||
char *REDISMODULE_API_FUNC(RedisModule_StringDMA)(RedisModuleKey *key, size_t *len, int mode);
|
||||
int REDISMODULE_API_FUNC(RedisModule_StringTruncate)(RedisModuleKey *key, size_t newlen);
|
||||
mstime_t REDISMODULE_API_FUNC(RedisModule_GetExpire)(RedisModuleKey *key);
|
||||
int REDISMODULE_API_FUNC(RedisModule_SetExpire)(RedisModuleKey *key, mstime_t expire);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ZsetAdd)(RedisModuleKey *key, double score, RedisModuleString *ele, int *flagsptr);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ZsetIncrby)(RedisModuleKey *key, double score, RedisModuleString *ele, int *flagsptr, double *newscore);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ZsetScore)(RedisModuleKey *key, RedisModuleString *ele, double *score);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ZsetRem)(RedisModuleKey *key, RedisModuleString *ele, int *deleted);
|
||||
void REDISMODULE_API_FUNC(RedisModule_ZsetRangeStop)(RedisModuleKey *key);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ZsetFirstInScoreRange)(RedisModuleKey *key, double min, double max, int minex, int maxex);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ZsetLastInScoreRange)(RedisModuleKey *key, double min, double max, int minex, int maxex);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ZsetFirstInLexRange)(RedisModuleKey *key, RedisModuleString *min, RedisModuleString *max);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ZsetLastInLexRange)(RedisModuleKey *key, RedisModuleString *min, RedisModuleString *max);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_ZsetRangeCurrentElement)(RedisModuleKey *key, double *score);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ZsetRangeNext)(RedisModuleKey *key);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ZsetRangePrev)(RedisModuleKey *key);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ZsetRangeEndReached)(RedisModuleKey *key);
|
||||
int REDISMODULE_API_FUNC(RedisModule_HashSet)(RedisModuleKey *key, int flags, ...);
|
||||
int REDISMODULE_API_FUNC(RedisModule_HashGet)(RedisModuleKey *key, int flags, ...);
|
||||
int REDISMODULE_API_FUNC(RedisModule_IsKeysPositionRequest)(RedisModuleCtx *ctx);
|
||||
void REDISMODULE_API_FUNC(RedisModule_KeyAtPos)(RedisModuleCtx *ctx, int pos);
|
||||
unsigned long long REDISMODULE_API_FUNC(RedisModule_GetClientId)(RedisModuleCtx *ctx);
|
||||
int REDISMODULE_API_FUNC(RedisModule_GetContextFlags)(RedisModuleCtx *ctx);
|
||||
void *REDISMODULE_API_FUNC(RedisModule_PoolAlloc)(RedisModuleCtx *ctx, size_t bytes);
|
||||
RedisModuleType *REDISMODULE_API_FUNC(RedisModule_CreateDataType)(RedisModuleCtx *ctx, const char *name, int encver, RedisModuleTypeMethods *typemethods);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ModuleTypeSetValue)(RedisModuleKey *key, RedisModuleType *mt, void *value);
|
||||
RedisModuleType *REDISMODULE_API_FUNC(RedisModule_ModuleTypeGetType)(RedisModuleKey *key);
|
||||
void *REDISMODULE_API_FUNC(RedisModule_ModuleTypeGetValue)(RedisModuleKey *key);
|
||||
void REDISMODULE_API_FUNC(RedisModule_SaveUnsigned)(RedisModuleIO *io, uint64_t value);
|
||||
uint64_t REDISMODULE_API_FUNC(RedisModule_LoadUnsigned)(RedisModuleIO *io);
|
||||
void REDISMODULE_API_FUNC(RedisModule_SaveSigned)(RedisModuleIO *io, int64_t value);
|
||||
int64_t REDISMODULE_API_FUNC(RedisModule_LoadSigned)(RedisModuleIO *io);
|
||||
void REDISMODULE_API_FUNC(RedisModule_EmitAOF)(RedisModuleIO *io, const char *cmdname, const char *fmt, ...);
|
||||
void REDISMODULE_API_FUNC(RedisModule_SaveString)(RedisModuleIO *io, RedisModuleString *s);
|
||||
void REDISMODULE_API_FUNC(RedisModule_SaveStringBuffer)(RedisModuleIO *io, const char *str, size_t len);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_LoadString)(RedisModuleIO *io);
|
||||
char *REDISMODULE_API_FUNC(RedisModule_LoadStringBuffer)(RedisModuleIO *io, size_t *lenptr);
|
||||
void REDISMODULE_API_FUNC(RedisModule_SaveDouble)(RedisModuleIO *io, double value);
|
||||
double REDISMODULE_API_FUNC(RedisModule_LoadDouble)(RedisModuleIO *io);
|
||||
void REDISMODULE_API_FUNC(RedisModule_SaveFloat)(RedisModuleIO *io, float value);
|
||||
float REDISMODULE_API_FUNC(RedisModule_LoadFloat)(RedisModuleIO *io);
|
||||
void REDISMODULE_API_FUNC(RedisModule_Log)(RedisModuleCtx *ctx, const char *level, const char *fmt, ...);
|
||||
void REDISMODULE_API_FUNC(RedisModule_LogIOError)(RedisModuleIO *io, const char *levelstr, const char *fmt, ...);
|
||||
int REDISMODULE_API_FUNC(RedisModule_StringAppendBuffer)(RedisModuleCtx *ctx, RedisModuleString *str, const char *buf, size_t len);
|
||||
void REDISMODULE_API_FUNC(RedisModule_RetainString)(RedisModuleCtx *ctx, RedisModuleString *str);
|
||||
int REDISMODULE_API_FUNC(RedisModule_StringCompare)(RedisModuleString *a, RedisModuleString *b);
|
||||
RedisModuleCtx *REDISMODULE_API_FUNC(RedisModule_GetContextFromIO)(RedisModuleIO *io);
|
||||
const RedisModuleString *REDISMODULE_API_FUNC(RedisModule_GetKeyNameFromIO)(RedisModuleIO *io);
|
||||
long long REDISMODULE_API_FUNC(RedisModule_Milliseconds)(void);
|
||||
void REDISMODULE_API_FUNC(RedisModule_DigestAddStringBuffer)(RedisModuleDigest *md, unsigned char *ele, size_t len);
|
||||
void REDISMODULE_API_FUNC(RedisModule_DigestAddLongLong)(RedisModuleDigest *md, long long ele);
|
||||
void REDISMODULE_API_FUNC(RedisModule_DigestEndSequence)(RedisModuleDigest *md);
|
||||
RedisModuleDict *REDISMODULE_API_FUNC(RedisModule_CreateDict)(RedisModuleCtx *ctx);
|
||||
void REDISMODULE_API_FUNC(RedisModule_FreeDict)(RedisModuleCtx *ctx, RedisModuleDict *d);
|
||||
uint64_t REDISMODULE_API_FUNC(RedisModule_DictSize)(RedisModuleDict *d);
|
||||
int REDISMODULE_API_FUNC(RedisModule_DictSetC)(RedisModuleDict *d, void *key, size_t keylen, void *ptr);
|
||||
int REDISMODULE_API_FUNC(RedisModule_DictReplaceC)(RedisModuleDict *d, void *key, size_t keylen, void *ptr);
|
||||
int REDISMODULE_API_FUNC(RedisModule_DictSet)(RedisModuleDict *d, RedisModuleString *key, void *ptr);
|
||||
int REDISMODULE_API_FUNC(RedisModule_DictReplace)(RedisModuleDict *d, RedisModuleString *key, void *ptr);
|
||||
void *REDISMODULE_API_FUNC(RedisModule_DictGetC)(RedisModuleDict *d, void *key, size_t keylen, int *nokey);
|
||||
void *REDISMODULE_API_FUNC(RedisModule_DictGet)(RedisModuleDict *d, RedisModuleString *key, int *nokey);
|
||||
int REDISMODULE_API_FUNC(RedisModule_DictDelC)(RedisModuleDict *d, void *key, size_t keylen, void *oldval);
|
||||
int REDISMODULE_API_FUNC(RedisModule_DictDel)(RedisModuleDict *d, RedisModuleString *key, void *oldval);
|
||||
RedisModuleDictIter *REDISMODULE_API_FUNC(RedisModule_DictIteratorStartC)(RedisModuleDict *d, const char *op, void *key, size_t keylen);
|
||||
RedisModuleDictIter *REDISMODULE_API_FUNC(RedisModule_DictIteratorStart)(RedisModuleDict *d, const char *op, RedisModuleString *key);
|
||||
void REDISMODULE_API_FUNC(RedisModule_DictIteratorStop)(RedisModuleDictIter *di);
|
||||
int REDISMODULE_API_FUNC(RedisModule_DictIteratorReseekC)(RedisModuleDictIter *di, const char *op, void *key, size_t keylen);
|
||||
int REDISMODULE_API_FUNC(RedisModule_DictIteratorReseek)(RedisModuleDictIter *di, const char *op, RedisModuleString *key);
|
||||
void *REDISMODULE_API_FUNC(RedisModule_DictNextC)(RedisModuleDictIter *di, size_t *keylen, void **dataptr);
|
||||
void *REDISMODULE_API_FUNC(RedisModule_DictPrevC)(RedisModuleDictIter *di, size_t *keylen, void **dataptr);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_DictNext)(RedisModuleCtx *ctx, RedisModuleDictIter *di, void **dataptr);
|
||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_DictPrev)(RedisModuleCtx *ctx, RedisModuleDictIter *di, void **dataptr);
|
||||
int REDISMODULE_API_FUNC(RedisModule_DictCompareC)(RedisModuleDictIter *di, const char *op, void *key, size_t keylen);
|
||||
int REDISMODULE_API_FUNC(RedisModule_DictCompare)(RedisModuleDictIter *di, const char *op, RedisModuleString *key);
|
||||
|
||||
/* Experimental APIs */
|
||||
#ifdef REDISMODULE_EXPERIMENTAL_API
|
||||
#define REDISMODULE_EXPERIMENTAL_API_VERSION 3
|
||||
RedisModuleBlockedClient *REDISMODULE_API_FUNC(RedisModule_BlockClient)(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms);
|
||||
int REDISMODULE_API_FUNC(RedisModule_UnblockClient)(RedisModuleBlockedClient *bc, void *privdata);
|
||||
int REDISMODULE_API_FUNC(RedisModule_IsBlockedReplyRequest)(RedisModuleCtx *ctx);
|
||||
int REDISMODULE_API_FUNC(RedisModule_IsBlockedTimeoutRequest)(RedisModuleCtx *ctx);
|
||||
void *REDISMODULE_API_FUNC(RedisModule_GetBlockedClientPrivateData)(RedisModuleCtx *ctx);
|
||||
RedisModuleBlockedClient *REDISMODULE_API_FUNC(RedisModule_GetBlockedClientHandle)(RedisModuleCtx *ctx);
|
||||
int REDISMODULE_API_FUNC(RedisModule_AbortBlock)(RedisModuleBlockedClient *bc);
|
||||
RedisModuleCtx *REDISMODULE_API_FUNC(RedisModule_GetThreadSafeContext)(RedisModuleBlockedClient *bc);
|
||||
void REDISMODULE_API_FUNC(RedisModule_FreeThreadSafeContext)(RedisModuleCtx *ctx);
|
||||
void REDISMODULE_API_FUNC(RedisModule_ThreadSafeContextLock)(RedisModuleCtx *ctx);
|
||||
void REDISMODULE_API_FUNC(RedisModule_ThreadSafeContextUnlock)(RedisModuleCtx *ctx);
|
||||
int REDISMODULE_API_FUNC(RedisModule_SubscribeToKeyspaceEvents)(RedisModuleCtx *ctx, int types, RedisModuleNotificationFunc cb);
|
||||
int REDISMODULE_API_FUNC(RedisModule_BlockedClientDisconnected)(RedisModuleCtx *ctx);
|
||||
void REDISMODULE_API_FUNC(RedisModule_RegisterClusterMessageReceiver)(RedisModuleCtx *ctx, uint8_t type, RedisModuleClusterMessageReceiver callback);
|
||||
int REDISMODULE_API_FUNC(RedisModule_SendClusterMessage)(RedisModuleCtx *ctx, char *target_id, uint8_t type, unsigned char *msg, uint32_t len);
|
||||
int REDISMODULE_API_FUNC(RedisModule_GetClusterNodeInfo)(RedisModuleCtx *ctx, const char *id, char *ip, char *master_id, int *port, int *flags);
|
||||
char **REDISMODULE_API_FUNC(RedisModule_GetClusterNodesList)(RedisModuleCtx *ctx, size_t *numnodes);
|
||||
void REDISMODULE_API_FUNC(RedisModule_FreeClusterNodesList)(char **ids);
|
||||
RedisModuleTimerID REDISMODULE_API_FUNC(RedisModule_CreateTimer)(RedisModuleCtx *ctx, mstime_t period, RedisModuleTimerProc callback, void *data);
|
||||
int REDISMODULE_API_FUNC(RedisModule_StopTimer)(RedisModuleCtx *ctx, RedisModuleTimerID id, void **data);
|
||||
int REDISMODULE_API_FUNC(RedisModule_GetTimerInfo)(RedisModuleCtx *ctx, RedisModuleTimerID id, uint64_t *remaining, void **data);
|
||||
const char *REDISMODULE_API_FUNC(RedisModule_GetMyClusterID)(void);
|
||||
size_t REDISMODULE_API_FUNC(RedisModule_GetClusterSize)(void);
|
||||
void REDISMODULE_API_FUNC(RedisModule_GetRandomBytes)(unsigned char *dst, size_t len);
|
||||
void REDISMODULE_API_FUNC(RedisModule_GetRandomHexChars)(char *dst, size_t len);
|
||||
void REDISMODULE_API_FUNC(RedisModule_SetDisconnectCallback)(RedisModuleBlockedClient *bc, RedisModuleDisconnectFunc callback);
|
||||
void REDISMODULE_API_FUNC(RedisModule_SetClusterFlags)(RedisModuleCtx *ctx, uint64_t flags);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ExportSharedAPI)(RedisModuleCtx *ctx, const char *apiname, void *func);
|
||||
void *REDISMODULE_API_FUNC(RedisModule_GetSharedAPI)(RedisModuleCtx *ctx, const char *apiname);
|
||||
RedisModuleCommandFilter *REDISMODULE_API_FUNC(RedisModule_RegisterCommandFilter)(RedisModuleCtx *ctx, RedisModuleCommandFilterFunc cb, int flags);
|
||||
int REDISMODULE_API_FUNC(RedisModule_UnregisterCommandFilter)(RedisModuleCtx *ctx, RedisModuleCommandFilter *filter);
|
||||
int REDISMODULE_API_FUNC(RedisModule_CommandFilterArgsCount)(RedisModuleCommandFilterCtx *fctx);
|
||||
const RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CommandFilterArgGet)(RedisModuleCommandFilterCtx *fctx, int pos);
|
||||
int REDISMODULE_API_FUNC(RedisModule_CommandFilterArgInsert)(RedisModuleCommandFilterCtx *fctx, int pos, RedisModuleString *arg);
|
||||
int REDISMODULE_API_FUNC(RedisModule_CommandFilterArgReplace)(RedisModuleCommandFilterCtx *fctx, int pos, RedisModuleString *arg);
|
||||
int REDISMODULE_API_FUNC(RedisModule_CommandFilterArgDelete)(RedisModuleCommandFilterCtx *fctx, int pos);
|
||||
#endif
|
||||
|
||||
/* This is included inline inside each Redis module. */
|
||||
static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) __attribute__((unused));
|
||||
static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) {
|
||||
void *getapifuncptr = ((void**)ctx)[0];
|
||||
RedisModule_GetApi = (int (*)(const char *, void *)) (unsigned long)getapifuncptr;
|
||||
REDISMODULE_GET_API(Alloc);
|
||||
REDISMODULE_GET_API(Calloc);
|
||||
REDISMODULE_GET_API(Free);
|
||||
REDISMODULE_GET_API(Realloc);
|
||||
REDISMODULE_GET_API(Strdup);
|
||||
REDISMODULE_GET_API(CreateCommand);
|
||||
REDISMODULE_GET_API(SetModuleAttribs);
|
||||
REDISMODULE_GET_API(IsModuleNameBusy);
|
||||
REDISMODULE_GET_API(WrongArity);
|
||||
REDISMODULE_GET_API(ReplyWithLongLong);
|
||||
REDISMODULE_GET_API(ReplyWithError);
|
||||
REDISMODULE_GET_API(ReplyWithSimpleString);
|
||||
REDISMODULE_GET_API(ReplyWithArray);
|
||||
REDISMODULE_GET_API(ReplySetArrayLength);
|
||||
REDISMODULE_GET_API(ReplyWithStringBuffer);
|
||||
REDISMODULE_GET_API(ReplyWithCString);
|
||||
REDISMODULE_GET_API(ReplyWithString);
|
||||
REDISMODULE_GET_API(ReplyWithNull);
|
||||
REDISMODULE_GET_API(ReplyWithCallReply);
|
||||
REDISMODULE_GET_API(ReplyWithDouble);
|
||||
REDISMODULE_GET_API(ReplySetArrayLength);
|
||||
REDISMODULE_GET_API(GetSelectedDb);
|
||||
REDISMODULE_GET_API(SelectDb);
|
||||
REDISMODULE_GET_API(OpenKey);
|
||||
REDISMODULE_GET_API(CloseKey);
|
||||
REDISMODULE_GET_API(KeyType);
|
||||
REDISMODULE_GET_API(ValueLength);
|
||||
REDISMODULE_GET_API(ListPush);
|
||||
REDISMODULE_GET_API(ListPop);
|
||||
REDISMODULE_GET_API(StringToLongLong);
|
||||
REDISMODULE_GET_API(StringToDouble);
|
||||
REDISMODULE_GET_API(Call);
|
||||
REDISMODULE_GET_API(CallReplyProto);
|
||||
REDISMODULE_GET_API(FreeCallReply);
|
||||
REDISMODULE_GET_API(CallReplyInteger);
|
||||
REDISMODULE_GET_API(CallReplyType);
|
||||
REDISMODULE_GET_API(CallReplyLength);
|
||||
REDISMODULE_GET_API(CallReplyArrayElement);
|
||||
REDISMODULE_GET_API(CallReplyStringPtr);
|
||||
REDISMODULE_GET_API(CreateStringFromCallReply);
|
||||
REDISMODULE_GET_API(CreateString);
|
||||
REDISMODULE_GET_API(CreateStringFromLongLong);
|
||||
REDISMODULE_GET_API(CreateStringFromString);
|
||||
REDISMODULE_GET_API(CreateStringPrintf);
|
||||
REDISMODULE_GET_API(FreeString);
|
||||
REDISMODULE_GET_API(StringPtrLen);
|
||||
REDISMODULE_GET_API(AutoMemory);
|
||||
REDISMODULE_GET_API(Replicate);
|
||||
REDISMODULE_GET_API(ReplicateVerbatim);
|
||||
REDISMODULE_GET_API(DeleteKey);
|
||||
REDISMODULE_GET_API(UnlinkKey);
|
||||
REDISMODULE_GET_API(StringSet);
|
||||
REDISMODULE_GET_API(StringDMA);
|
||||
REDISMODULE_GET_API(StringTruncate);
|
||||
REDISMODULE_GET_API(GetExpire);
|
||||
REDISMODULE_GET_API(SetExpire);
|
||||
REDISMODULE_GET_API(ZsetAdd);
|
||||
REDISMODULE_GET_API(ZsetIncrby);
|
||||
REDISMODULE_GET_API(ZsetScore);
|
||||
REDISMODULE_GET_API(ZsetRem);
|
||||
REDISMODULE_GET_API(ZsetRangeStop);
|
||||
REDISMODULE_GET_API(ZsetFirstInScoreRange);
|
||||
REDISMODULE_GET_API(ZsetLastInScoreRange);
|
||||
REDISMODULE_GET_API(ZsetFirstInLexRange);
|
||||
REDISMODULE_GET_API(ZsetLastInLexRange);
|
||||
REDISMODULE_GET_API(ZsetRangeCurrentElement);
|
||||
REDISMODULE_GET_API(ZsetRangeNext);
|
||||
REDISMODULE_GET_API(ZsetRangePrev);
|
||||
REDISMODULE_GET_API(ZsetRangeEndReached);
|
||||
REDISMODULE_GET_API(HashSet);
|
||||
REDISMODULE_GET_API(HashGet);
|
||||
REDISMODULE_GET_API(IsKeysPositionRequest);
|
||||
REDISMODULE_GET_API(KeyAtPos);
|
||||
REDISMODULE_GET_API(GetClientId);
|
||||
REDISMODULE_GET_API(GetContextFlags);
|
||||
REDISMODULE_GET_API(PoolAlloc);
|
||||
REDISMODULE_GET_API(CreateDataType);
|
||||
REDISMODULE_GET_API(ModuleTypeSetValue);
|
||||
REDISMODULE_GET_API(ModuleTypeGetType);
|
||||
REDISMODULE_GET_API(ModuleTypeGetValue);
|
||||
REDISMODULE_GET_API(SaveUnsigned);
|
||||
REDISMODULE_GET_API(LoadUnsigned);
|
||||
REDISMODULE_GET_API(SaveSigned);
|
||||
REDISMODULE_GET_API(LoadSigned);
|
||||
REDISMODULE_GET_API(SaveString);
|
||||
REDISMODULE_GET_API(SaveStringBuffer);
|
||||
REDISMODULE_GET_API(LoadString);
|
||||
REDISMODULE_GET_API(LoadStringBuffer);
|
||||
REDISMODULE_GET_API(SaveDouble);
|
||||
REDISMODULE_GET_API(LoadDouble);
|
||||
REDISMODULE_GET_API(SaveFloat);
|
||||
REDISMODULE_GET_API(LoadFloat);
|
||||
REDISMODULE_GET_API(EmitAOF);
|
||||
REDISMODULE_GET_API(Log);
|
||||
REDISMODULE_GET_API(LogIOError);
|
||||
REDISMODULE_GET_API(StringAppendBuffer);
|
||||
REDISMODULE_GET_API(RetainString);
|
||||
REDISMODULE_GET_API(StringCompare);
|
||||
REDISMODULE_GET_API(GetContextFromIO);
|
||||
REDISMODULE_GET_API(GetKeyNameFromIO);
|
||||
REDISMODULE_GET_API(Milliseconds);
|
||||
REDISMODULE_GET_API(DigestAddStringBuffer);
|
||||
REDISMODULE_GET_API(DigestAddLongLong);
|
||||
REDISMODULE_GET_API(DigestEndSequence);
|
||||
REDISMODULE_GET_API(CreateDict);
|
||||
REDISMODULE_GET_API(FreeDict);
|
||||
REDISMODULE_GET_API(DictSize);
|
||||
REDISMODULE_GET_API(DictSetC);
|
||||
REDISMODULE_GET_API(DictReplaceC);
|
||||
REDISMODULE_GET_API(DictSet);
|
||||
REDISMODULE_GET_API(DictReplace);
|
||||
REDISMODULE_GET_API(DictGetC);
|
||||
REDISMODULE_GET_API(DictGet);
|
||||
REDISMODULE_GET_API(DictDelC);
|
||||
REDISMODULE_GET_API(DictDel);
|
||||
REDISMODULE_GET_API(DictIteratorStartC);
|
||||
REDISMODULE_GET_API(DictIteratorStart);
|
||||
REDISMODULE_GET_API(DictIteratorStop);
|
||||
REDISMODULE_GET_API(DictIteratorReseekC);
|
||||
REDISMODULE_GET_API(DictIteratorReseek);
|
||||
REDISMODULE_GET_API(DictNextC);
|
||||
REDISMODULE_GET_API(DictPrevC);
|
||||
REDISMODULE_GET_API(DictNext);
|
||||
REDISMODULE_GET_API(DictPrev);
|
||||
REDISMODULE_GET_API(DictCompare);
|
||||
REDISMODULE_GET_API(DictCompareC);
|
||||
|
||||
#ifdef REDISMODULE_EXPERIMENTAL_API
|
||||
REDISMODULE_GET_API(GetThreadSafeContext);
|
||||
REDISMODULE_GET_API(FreeThreadSafeContext);
|
||||
REDISMODULE_GET_API(ThreadSafeContextLock);
|
||||
REDISMODULE_GET_API(ThreadSafeContextUnlock);
|
||||
REDISMODULE_GET_API(BlockClient);
|
||||
REDISMODULE_GET_API(UnblockClient);
|
||||
REDISMODULE_GET_API(IsBlockedReplyRequest);
|
||||
REDISMODULE_GET_API(IsBlockedTimeoutRequest);
|
||||
REDISMODULE_GET_API(GetBlockedClientPrivateData);
|
||||
REDISMODULE_GET_API(GetBlockedClientHandle);
|
||||
REDISMODULE_GET_API(AbortBlock);
|
||||
REDISMODULE_GET_API(SetDisconnectCallback);
|
||||
REDISMODULE_GET_API(SubscribeToKeyspaceEvents);
|
||||
REDISMODULE_GET_API(BlockedClientDisconnected);
|
||||
REDISMODULE_GET_API(RegisterClusterMessageReceiver);
|
||||
REDISMODULE_GET_API(SendClusterMessage);
|
||||
REDISMODULE_GET_API(GetClusterNodeInfo);
|
||||
REDISMODULE_GET_API(GetClusterNodesList);
|
||||
REDISMODULE_GET_API(FreeClusterNodesList);
|
||||
REDISMODULE_GET_API(CreateTimer);
|
||||
REDISMODULE_GET_API(StopTimer);
|
||||
REDISMODULE_GET_API(GetTimerInfo);
|
||||
REDISMODULE_GET_API(GetMyClusterID);
|
||||
REDISMODULE_GET_API(GetClusterSize);
|
||||
REDISMODULE_GET_API(GetRandomBytes);
|
||||
REDISMODULE_GET_API(GetRandomHexChars);
|
||||
REDISMODULE_GET_API(SetClusterFlags);
|
||||
REDISMODULE_GET_API(ExportSharedAPI);
|
||||
REDISMODULE_GET_API(GetSharedAPI);
|
||||
REDISMODULE_GET_API(RegisterCommandFilter);
|
||||
REDISMODULE_GET_API(UnregisterCommandFilter);
|
||||
REDISMODULE_GET_API(CommandFilterArgsCount);
|
||||
REDISMODULE_GET_API(CommandFilterArgGet);
|
||||
REDISMODULE_GET_API(CommandFilterArgInsert);
|
||||
REDISMODULE_GET_API(CommandFilterArgReplace);
|
||||
REDISMODULE_GET_API(CommandFilterArgDelete);
|
||||
#endif
|
||||
|
||||
if (RedisModule_IsModuleNameBusy && RedisModule_IsModuleNameBusy(name)) return REDISMODULE_ERR;
|
||||
RedisModule_SetModuleAttribs(ctx,name,ver,apiver);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Things only defined for the modules core, not exported to modules
|
||||
* including this file. */
|
||||
#define RedisModuleString robj
|
||||
|
||||
#endif /* REDISMODULE_CORE */
|
||||
#endif /* REDISMOUDLE_H */
|
586
setup/dbaas/redismodule/m4/ax_prog_doxygen.m4
Executable file
586
setup/dbaas/redismodule/m4/ax_prog_doxygen.m4
Executable file
@@ -0,0 +1,586 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# DX_INIT_DOXYGEN(PROJECT-NAME, [DOXYFILE-PATH], [OUTPUT-DIR], ...)
|
||||
# DX_DOXYGEN_FEATURE(ON|OFF)
|
||||
# DX_DOT_FEATURE(ON|OFF)
|
||||
# DX_HTML_FEATURE(ON|OFF)
|
||||
# DX_CHM_FEATURE(ON|OFF)
|
||||
# DX_CHI_FEATURE(ON|OFF)
|
||||
# DX_MAN_FEATURE(ON|OFF)
|
||||
# DX_RTF_FEATURE(ON|OFF)
|
||||
# DX_XML_FEATURE(ON|OFF)
|
||||
# DX_PDF_FEATURE(ON|OFF)
|
||||
# DX_PS_FEATURE(ON|OFF)
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# The DX_*_FEATURE macros control the default setting for the given
|
||||
# Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for
|
||||
# generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML
|
||||
# help (for MS users), 'CHI' for generating a separate .chi file by the
|
||||
# .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate
|
||||
# output formats. The environment variable DOXYGEN_PAPER_SIZE may be
|
||||
# specified to override the default 'a4wide' paper size.
|
||||
#
|
||||
# By default, HTML, PDF and PS documentation is generated as this seems to
|
||||
# be the most popular and portable combination. MAN pages created by
|
||||
# Doxygen are usually problematic, though by picking an appropriate subset
|
||||
# and doing some massaging they might be better than nothing. CHM and RTF
|
||||
# are specific for MS (note that you can't generate both HTML and CHM at
|
||||
# the same time). The XML is rather useless unless you apply specialized
|
||||
# post-processing to it.
|
||||
#
|
||||
# The macros mainly control the default state of the feature. The use can
|
||||
# override the default by specifying --enable or --disable. The macros
|
||||
# ensure that contradictory flags are not given (e.g.,
|
||||
# --enable-doxygen-html and --enable-doxygen-chm,
|
||||
# --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each
|
||||
# feature will be automatically disabled (with a warning) if the required
|
||||
# programs are missing.
|
||||
#
|
||||
# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN
|
||||
# with the following parameters: a one-word name for the project for use
|
||||
# as a filename base etc., an optional configuration file name (the
|
||||
# default is '$(srcdir)/Doxyfile', the same as Doxygen's default), and an
|
||||
# optional output directory name (the default is 'doxygen-doc'). To run
|
||||
# doxygen multiple times for different configuration files and output
|
||||
# directories provide more parameters: the second, forth, sixth, etc
|
||||
# parameter are configuration file names and the third, fifth, seventh,
|
||||
# etc parameter are output directories. No checking is done to catch
|
||||
# duplicates.
|
||||
#
|
||||
# Automake Support
|
||||
#
|
||||
# The DX_RULES substitution can be used to add all needed rules to the
|
||||
# Makefile. Note that this is a substitution without being a variable:
|
||||
# only the @DX_RULES@ syntax will work.
|
||||
#
|
||||
# The provided targets are:
|
||||
#
|
||||
# doxygen-doc: Generate all doxygen documentation.
|
||||
#
|
||||
# doxygen-run: Run doxygen, which will generate some of the
|
||||
# documentation (HTML, CHM, CHI, MAN, RTF, XML)
|
||||
# but will not do the post processing required
|
||||
# for the rest of it (PS, PDF).
|
||||
#
|
||||
# doxygen-ps: Generate doxygen PostScript documentation.
|
||||
#
|
||||
# doxygen-pdf: Generate doxygen PDF documentation.
|
||||
#
|
||||
# Note that by default these are not integrated into the automake targets.
|
||||
# If doxygen is used to generate man pages, you can achieve this
|
||||
# integration by setting man3_MANS to the list of man pages generated and
|
||||
# then adding the dependency:
|
||||
#
|
||||
# $(man3_MANS): doxygen-doc
|
||||
#
|
||||
# This will cause make to run doxygen and generate all the documentation.
|
||||
#
|
||||
# The following variable is intended for use in Makefile.am:
|
||||
#
|
||||
# DX_CLEANFILES = everything to clean.
|
||||
#
|
||||
# Then add this variable to MOSTLYCLEANFILES.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2009 Oren Ben-Kiki <oren@ben-kiki.org>
|
||||
# Copyright (c) 2015 Olaf Mandel <olaf@mandel.name>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 23
|
||||
|
||||
## ----------##
|
||||
## Defaults. ##
|
||||
## ----------##
|
||||
|
||||
DX_ENV=""
|
||||
AC_DEFUN([DX_FEATURE_doc], ON)
|
||||
AC_DEFUN([DX_FEATURE_dot], OFF)
|
||||
AC_DEFUN([DX_FEATURE_man], OFF)
|
||||
AC_DEFUN([DX_FEATURE_html], ON)
|
||||
AC_DEFUN([DX_FEATURE_chm], OFF)
|
||||
AC_DEFUN([DX_FEATURE_chi], OFF)
|
||||
AC_DEFUN([DX_FEATURE_rtf], OFF)
|
||||
AC_DEFUN([DX_FEATURE_xml], OFF)
|
||||
AC_DEFUN([DX_FEATURE_pdf], ON)
|
||||
AC_DEFUN([DX_FEATURE_ps], ON)
|
||||
|
||||
## --------------- ##
|
||||
## Private macros. ##
|
||||
## --------------- ##
|
||||
|
||||
# DX_ENV_APPEND(VARIABLE, VALUE)
|
||||
# ------------------------------
|
||||
# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen and add it
|
||||
# as a substitution (but not a Makefile variable). The substitution
|
||||
# is skipped if the variable name is VERSION.
|
||||
AC_DEFUN([DX_ENV_APPEND],
|
||||
[AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])dnl
|
||||
m4_if([$1], [VERSION], [], [AC_SUBST([$1], [$2])dnl
|
||||
AM_SUBST_NOTMAKE([$1])])dnl
|
||||
])
|
||||
|
||||
# DX_DIRNAME_EXPR
|
||||
# ---------------
|
||||
# Expand into a shell expression prints the directory part of a path.
|
||||
AC_DEFUN([DX_DIRNAME_EXPR],
|
||||
[[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
|
||||
|
||||
# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
|
||||
# -------------------------------------
|
||||
# Expands according to the M4 (static) status of the feature.
|
||||
AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
|
||||
|
||||
# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
|
||||
# ----------------------------------
|
||||
# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
|
||||
AC_DEFUN([DX_REQUIRE_PROG], [
|
||||
AC_PATH_TOOL([$1], [$2])
|
||||
if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then
|
||||
AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
|
||||
AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
|
||||
fi
|
||||
])
|
||||
|
||||
# DX_TEST_FEATURE(FEATURE)
|
||||
# ------------------------
|
||||
# Expand to a shell expression testing whether the feature is active.
|
||||
AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
|
||||
|
||||
# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
|
||||
# -------------------------------------------------
|
||||
# Verify that a required features has the right state before trying to turn on
|
||||
# the DX_CURRENT_FEATURE.
|
||||
AC_DEFUN([DX_CHECK_DEPEND], [
|
||||
test "$DX_FLAG_$1" = "$2" \
|
||||
|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
|
||||
requires, contradicts) doxygen-DX_CURRENT_FEATURE])
|
||||
])
|
||||
|
||||
# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
|
||||
# ----------------------------------------------------------
|
||||
# Turn off the DX_CURRENT_FEATURE if the required feature is off.
|
||||
AC_DEFUN([DX_CLEAR_DEPEND], [
|
||||
test "$DX_FLAG_$1" = "$2" || AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
|
||||
])
|
||||
|
||||
# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
|
||||
# CHECK_DEPEND, CLEAR_DEPEND,
|
||||
# REQUIRE, DO-IF-ON, DO-IF-OFF)
|
||||
# --------------------------------------------
|
||||
# Parse the command-line option controlling a feature. CHECK_DEPEND is called
|
||||
# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
|
||||
# otherwise CLEAR_DEPEND is called to turn off the default state if a required
|
||||
# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
|
||||
# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
|
||||
# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
|
||||
AC_DEFUN([DX_ARG_ABLE], [
|
||||
AC_DEFUN([DX_CURRENT_FEATURE], [$1])
|
||||
AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
|
||||
AC_ARG_ENABLE(doxygen-$1,
|
||||
[AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
|
||||
[--enable-doxygen-$1]),
|
||||
DX_IF_FEATURE([$1], [don't $2], [$2]))],
|
||||
[
|
||||
case "$enableval" in
|
||||
#(
|
||||
y|Y|yes|Yes|YES)
|
||||
AC_SUBST([DX_FLAG_$1], 1)
|
||||
$3
|
||||
;; #(
|
||||
n|N|no|No|NO)
|
||||
AC_SUBST([DX_FLAG_$1], 0)
|
||||
;; #(
|
||||
*)
|
||||
AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
|
||||
;;
|
||||
esac
|
||||
], [
|
||||
AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
|
||||
$4
|
||||
])
|
||||
if DX_TEST_FEATURE([$1]); then
|
||||
$5
|
||||
:
|
||||
fi
|
||||
if DX_TEST_FEATURE([$1]); then
|
||||
$6
|
||||
:
|
||||
else
|
||||
$7
|
||||
:
|
||||
fi
|
||||
])
|
||||
|
||||
## -------------- ##
|
||||
## Public macros. ##
|
||||
## -------------- ##
|
||||
|
||||
# DX_XXX_FEATURE(DEFAULT_STATE)
|
||||
# -----------------------------
|
||||
AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
|
||||
AC_DEFUN([DX_DOT_FEATURE], [AC_DEFUN([DX_FEATURE_dot], [$1])])
|
||||
AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
|
||||
AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
|
||||
AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
|
||||
AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
|
||||
AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
|
||||
AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
|
||||
AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
|
||||
AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
|
||||
AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
|
||||
|
||||
# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR], ...)
|
||||
# --------------------------------------------------------------
|
||||
# PROJECT also serves as the base name for the documentation files.
|
||||
# The default CONFIG-FILE is "$(srcdir)/Doxyfile" and OUTPUT-DOC-DIR is
|
||||
# "doxygen-doc".
|
||||
# More arguments are interpreted as interleaved CONFIG-FILE and
|
||||
# OUTPUT-DOC-DIR values.
|
||||
AC_DEFUN([DX_INIT_DOXYGEN], [
|
||||
|
||||
# Files:
|
||||
AC_SUBST([DX_PROJECT], [$1])
|
||||
AC_SUBST([DX_CONFIG], ['ifelse([$2], [], [$(srcdir)/Doxyfile], [$2])'])
|
||||
AC_SUBST([DX_DOCDIR], ['ifelse([$3], [], [doxygen-doc], [$3])'])
|
||||
m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 4, m4_count($@), 2,
|
||||
[AC_SUBST([DX_CONFIG]m4_eval(DX_i[/2]),
|
||||
'm4_default_nblank_quoted(m4_argn(DX_i, $@),
|
||||
[$(srcdir)/Doxyfile])')])])dnl
|
||||
m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 5, m4_count($@,), 2,
|
||||
[AC_SUBST([DX_DOCDIR]m4_eval([(]DX_i[-1)/2]),
|
||||
'm4_default_nblank_quoted(m4_argn(DX_i, $@),
|
||||
[doxygen-doc])')])])dnl
|
||||
m4_define([DX_loop], m4_dquote(m4_if(m4_eval(3 < m4_count($@)), 1,
|
||||
[m4_for([DX_i], 4, m4_count($@), 2, [, m4_eval(DX_i[/2])])],
|
||||
[])))dnl
|
||||
|
||||
# Environment variables used inside doxygen.cfg:
|
||||
DX_ENV_APPEND(SRCDIR, $srcdir)
|
||||
DX_ENV_APPEND(PROJECT, $DX_PROJECT)
|
||||
DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
|
||||
|
||||
# Doxygen itself:
|
||||
DX_ARG_ABLE(doc, [generate any doxygen documentation],
|
||||
[],
|
||||
[],
|
||||
[DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
|
||||
DX_REQUIRE_PROG([DX_PERL], perl)],
|
||||
[DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
|
||||
|
||||
# Dot for graphics:
|
||||
DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
|
||||
[DX_CHECK_DEPEND(doc, 1)],
|
||||
[DX_CLEAR_DEPEND(doc, 1)],
|
||||
[DX_REQUIRE_PROG([DX_DOT], dot)],
|
||||
[DX_ENV_APPEND(HAVE_DOT, YES)
|
||||
DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
|
||||
[DX_ENV_APPEND(HAVE_DOT, NO)])
|
||||
|
||||
# Man pages generation:
|
||||
DX_ARG_ABLE(man, [generate doxygen manual pages],
|
||||
[DX_CHECK_DEPEND(doc, 1)],
|
||||
[DX_CLEAR_DEPEND(doc, 1)],
|
||||
[],
|
||||
[DX_ENV_APPEND(GENERATE_MAN, YES)],
|
||||
[DX_ENV_APPEND(GENERATE_MAN, NO)])
|
||||
|
||||
# RTF file generation:
|
||||
DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
|
||||
[DX_CHECK_DEPEND(doc, 1)],
|
||||
[DX_CLEAR_DEPEND(doc, 1)],
|
||||
[],
|
||||
[DX_ENV_APPEND(GENERATE_RTF, YES)],
|
||||
[DX_ENV_APPEND(GENERATE_RTF, NO)])
|
||||
|
||||
# XML file generation:
|
||||
DX_ARG_ABLE(xml, [generate doxygen XML documentation],
|
||||
[DX_CHECK_DEPEND(doc, 1)],
|
||||
[DX_CLEAR_DEPEND(doc, 1)],
|
||||
[],
|
||||
[DX_ENV_APPEND(GENERATE_XML, YES)],
|
||||
[DX_ENV_APPEND(GENERATE_XML, NO)])
|
||||
|
||||
# (Compressed) HTML help generation:
|
||||
DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
|
||||
[DX_CHECK_DEPEND(doc, 1)],
|
||||
[DX_CLEAR_DEPEND(doc, 1)],
|
||||
[DX_REQUIRE_PROG([DX_HHC], hhc)],
|
||||
[DX_ENV_APPEND(HHC_PATH, $DX_HHC)
|
||||
DX_ENV_APPEND(GENERATE_HTML, YES)
|
||||
DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
|
||||
[DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
|
||||
|
||||
# Separate CHI file generation.
|
||||
DX_ARG_ABLE(chi, [generate doxygen separate compressed HTML help index file],
|
||||
[DX_CHECK_DEPEND(chm, 1)],
|
||||
[DX_CLEAR_DEPEND(chm, 1)],
|
||||
[],
|
||||
[DX_ENV_APPEND(GENERATE_CHI, YES)],
|
||||
[DX_ENV_APPEND(GENERATE_CHI, NO)])
|
||||
|
||||
# Plain HTML pages generation:
|
||||
DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
|
||||
[DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
|
||||
[DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
|
||||
[],
|
||||
[DX_ENV_APPEND(GENERATE_HTML, YES)],
|
||||
[DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
|
||||
|
||||
# PostScript file generation:
|
||||
DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
|
||||
[DX_CHECK_DEPEND(doc, 1)],
|
||||
[DX_CLEAR_DEPEND(doc, 1)],
|
||||
[DX_REQUIRE_PROG([DX_LATEX], latex)
|
||||
DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
|
||||
DX_REQUIRE_PROG([DX_DVIPS], dvips)
|
||||
DX_REQUIRE_PROG([DX_EGREP], egrep)])
|
||||
|
||||
# PDF file generation:
|
||||
DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
|
||||
[DX_CHECK_DEPEND(doc, 1)],
|
||||
[DX_CLEAR_DEPEND(doc, 1)],
|
||||
[DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
|
||||
DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
|
||||
DX_REQUIRE_PROG([DX_EGREP], egrep)])
|
||||
|
||||
# LaTeX generation for PS and/or PDF:
|
||||
if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
|
||||
DX_ENV_APPEND(GENERATE_LATEX, YES)
|
||||
else
|
||||
DX_ENV_APPEND(GENERATE_LATEX, NO)
|
||||
fi
|
||||
|
||||
# Paper size for PS and/or PDF:
|
||||
AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
|
||||
[a4wide (default), a4, letter, legal or executive])
|
||||
case "$DOXYGEN_PAPER_SIZE" in
|
||||
#(
|
||||
"")
|
||||
AC_SUBST(DOXYGEN_PAPER_SIZE, "")
|
||||
;; #(
|
||||
a4wide|a4|letter|legal|executive)
|
||||
DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
|
||||
;; #(
|
||||
*)
|
||||
AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
|
||||
;;
|
||||
esac
|
||||
|
||||
# Rules:
|
||||
AS_IF([[test $DX_FLAG_html -eq 1]],
|
||||
[[DX_SNIPPET_html="## ------------------------------- ##
|
||||
## Rules specific for HTML output. ##
|
||||
## ------------------------------- ##
|
||||
|
||||
DX_CLEAN_HTML = \$(DX_DOCDIR)/html]dnl
|
||||
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
|
||||
\$(DX_DOCDIR]DX_i[)/html]])[
|
||||
|
||||
"]],
|
||||
[[DX_SNIPPET_html=""]])
|
||||
AS_IF([[test $DX_FLAG_chi -eq 1]],
|
||||
[[DX_SNIPPET_chi="
|
||||
DX_CLEAN_CHI = \$(DX_DOCDIR)/\$(PACKAGE).chi]dnl
|
||||
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
|
||||
\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).chi]])["]],
|
||||
[[DX_SNIPPET_chi=""]])
|
||||
AS_IF([[test $DX_FLAG_chm -eq 1]],
|
||||
[[DX_SNIPPET_chm="## ------------------------------ ##
|
||||
## Rules specific for CHM output. ##
|
||||
## ------------------------------ ##
|
||||
|
||||
DX_CLEAN_CHM = \$(DX_DOCDIR)/chm]dnl
|
||||
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
|
||||
\$(DX_DOCDIR]DX_i[)/chm]])[\
|
||||
${DX_SNIPPET_chi}
|
||||
|
||||
"]],
|
||||
[[DX_SNIPPET_chm=""]])
|
||||
AS_IF([[test $DX_FLAG_man -eq 1]],
|
||||
[[DX_SNIPPET_man="## ------------------------------ ##
|
||||
## Rules specific for MAN output. ##
|
||||
## ------------------------------ ##
|
||||
|
||||
DX_CLEAN_MAN = \$(DX_DOCDIR)/man]dnl
|
||||
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
|
||||
\$(DX_DOCDIR]DX_i[)/man]])[
|
||||
|
||||
"]],
|
||||
[[DX_SNIPPET_man=""]])
|
||||
AS_IF([[test $DX_FLAG_rtf -eq 1]],
|
||||
[[DX_SNIPPET_rtf="## ------------------------------ ##
|
||||
## Rules specific for RTF output. ##
|
||||
## ------------------------------ ##
|
||||
|
||||
DX_CLEAN_RTF = \$(DX_DOCDIR)/rtf]dnl
|
||||
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
|
||||
\$(DX_DOCDIR]DX_i[)/rtf]])[
|
||||
|
||||
"]],
|
||||
[[DX_SNIPPET_rtf=""]])
|
||||
AS_IF([[test $DX_FLAG_xml -eq 1]],
|
||||
[[DX_SNIPPET_xml="## ------------------------------ ##
|
||||
## Rules specific for XML output. ##
|
||||
## ------------------------------ ##
|
||||
|
||||
DX_CLEAN_XML = \$(DX_DOCDIR)/xml]dnl
|
||||
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
|
||||
\$(DX_DOCDIR]DX_i[)/xml]])[
|
||||
|
||||
"]],
|
||||
[[DX_SNIPPET_xml=""]])
|
||||
AS_IF([[test $DX_FLAG_ps -eq 1]],
|
||||
[[DX_SNIPPET_ps="## ----------------------------- ##
|
||||
## Rules specific for PS output. ##
|
||||
## ----------------------------- ##
|
||||
|
||||
DX_CLEAN_PS = \$(DX_DOCDIR)/\$(PACKAGE).ps]dnl
|
||||
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
|
||||
\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps]])[
|
||||
|
||||
DX_PS_GOAL = doxygen-ps
|
||||
|
||||
doxygen-ps: \$(DX_CLEAN_PS)
|
||||
|
||||
]m4_foreach([DX_i], [DX_loop],
|
||||
[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag
|
||||
\$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\
|
||||
rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\
|
||||
\$(DX_LATEX) refman.tex; \\
|
||||
\$(DX_MAKEINDEX) refman.idx; \\
|
||||
\$(DX_LATEX) refman.tex; \\
|
||||
countdown=5; \\
|
||||
while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\
|
||||
refman.log > /dev/null 2>&1 \\
|
||||
&& test \$\$countdown -gt 0; do \\
|
||||
\$(DX_LATEX) refman.tex; \\
|
||||
countdown=\`expr \$\$countdown - 1\`; \\
|
||||
done; \\
|
||||
\$(DX_DVIPS) -o ../\$(PACKAGE).ps refman.dvi
|
||||
|
||||
]])["]],
|
||||
[[DX_SNIPPET_ps=""]])
|
||||
AS_IF([[test $DX_FLAG_pdf -eq 1]],
|
||||
[[DX_SNIPPET_pdf="## ------------------------------ ##
|
||||
## Rules specific for PDF output. ##
|
||||
## ------------------------------ ##
|
||||
|
||||
DX_CLEAN_PDF = \$(DX_DOCDIR)/\$(PACKAGE).pdf]dnl
|
||||
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
|
||||
\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf]])[
|
||||
|
||||
DX_PDF_GOAL = doxygen-pdf
|
||||
|
||||
doxygen-pdf: \$(DX_CLEAN_PDF)
|
||||
|
||||
]m4_foreach([DX_i], [DX_loop],
|
||||
[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag
|
||||
\$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\
|
||||
rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\
|
||||
\$(DX_PDFLATEX) refman.tex; \\
|
||||
\$(DX_MAKEINDEX) refman.idx; \\
|
||||
\$(DX_PDFLATEX) refman.tex; \\
|
||||
countdown=5; \\
|
||||
while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\
|
||||
refman.log > /dev/null 2>&1 \\
|
||||
&& test \$\$countdown -gt 0; do \\
|
||||
\$(DX_PDFLATEX) refman.tex; \\
|
||||
countdown=\`expr \$\$countdown - 1\`; \\
|
||||
done; \\
|
||||
mv refman.pdf ../\$(PACKAGE).pdf
|
||||
|
||||
]])["]],
|
||||
[[DX_SNIPPET_pdf=""]])
|
||||
AS_IF([[test $DX_FLAG_ps -eq 1 -o $DX_FLAG_pdf -eq 1]],
|
||||
[[DX_SNIPPET_latex="## ------------------------------------------------- ##
|
||||
## Rules specific for LaTeX (shared for PS and PDF). ##
|
||||
## ------------------------------------------------- ##
|
||||
|
||||
DX_V_LATEX = \$(_DX_v_LATEX_\$(V))
|
||||
_DX_v_LATEX_ = \$(_DX_v_LATEX_\$(AM_DEFAULT_VERBOSITY))
|
||||
_DX_v_LATEX_0 = @echo \" LATEX \" \$][@;
|
||||
|
||||
DX_CLEAN_LATEX = \$(DX_DOCDIR)/latex]dnl
|
||||
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
|
||||
\$(DX_DOCDIR]DX_i[)/latex]])[
|
||||
|
||||
"]],
|
||||
[[DX_SNIPPET_latex=""]])
|
||||
|
||||
AS_IF([[test $DX_FLAG_doc -eq 1]],
|
||||
[[DX_SNIPPET_doc="## --------------------------------- ##
|
||||
## Format-independent Doxygen rules. ##
|
||||
## --------------------------------- ##
|
||||
|
||||
${DX_SNIPPET_html}\
|
||||
${DX_SNIPPET_chm}\
|
||||
${DX_SNIPPET_man}\
|
||||
${DX_SNIPPET_rtf}\
|
||||
${DX_SNIPPET_xml}\
|
||||
${DX_SNIPPET_ps}\
|
||||
${DX_SNIPPET_pdf}\
|
||||
${DX_SNIPPET_latex}\
|
||||
DX_V_DXGEN = \$(_DX_v_DXGEN_\$(V))
|
||||
_DX_v_DXGEN_ = \$(_DX_v_DXGEN_\$(AM_DEFAULT_VERBOSITY))
|
||||
_DX_v_DXGEN_0 = @echo \" DXGEN \" \$<;
|
||||
|
||||
.PHONY: doxygen-run doxygen-doc \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
|
||||
|
||||
.INTERMEDIATE: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
|
||||
|
||||
doxygen-run:]m4_foreach([DX_i], [DX_loop],
|
||||
[[ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag]])[
|
||||
|
||||
doxygen-doc: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
|
||||
|
||||
]m4_foreach([DX_i], [DX_loop],
|
||||
[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag: \$(DX_CONFIG]DX_i[) \$(pkginclude_HEADERS)
|
||||
\$(A""M_V_at)rm -rf \$(DX_DOCDIR]DX_i[)
|
||||
\$(DX_V_DXGEN)\$(DX_ENV) DOCDIR=\$(DX_DOCDIR]DX_i[) \$(DX_DOXYGEN) \$(DX_CONFIG]DX_i[)
|
||||
\$(A""M_V_at)echo Timestamp >\$][@
|
||||
|
||||
]])dnl
|
||||
[DX_CLEANFILES = \\]
|
||||
m4_foreach([DX_i], [DX_loop],
|
||||
[[ \$(DX_DOCDIR]DX_i[)/doxygen_sqlite3.db \\
|
||||
\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag \\
|
||||
]])dnl
|
||||
[ -r \\
|
||||
\$(DX_CLEAN_HTML) \\
|
||||
\$(DX_CLEAN_CHM) \\
|
||||
\$(DX_CLEAN_CHI) \\
|
||||
\$(DX_CLEAN_MAN) \\
|
||||
\$(DX_CLEAN_RTF) \\
|
||||
\$(DX_CLEAN_XML) \\
|
||||
\$(DX_CLEAN_PS) \\
|
||||
\$(DX_CLEAN_PDF) \\
|
||||
\$(DX_CLEAN_LATEX)"]],
|
||||
[[DX_SNIPPET_doc=""]])
|
||||
AC_SUBST([DX_RULES],
|
||||
["${DX_SNIPPET_doc}"])dnl
|
||||
AM_SUBST_NOTMAKE([DX_RULES])
|
||||
|
||||
#For debugging:
|
||||
#echo DX_FLAG_doc=$DX_FLAG_doc
|
||||
#echo DX_FLAG_dot=$DX_FLAG_dot
|
||||
#echo DX_FLAG_man=$DX_FLAG_man
|
||||
#echo DX_FLAG_html=$DX_FLAG_html
|
||||
#echo DX_FLAG_chm=$DX_FLAG_chm
|
||||
#echo DX_FLAG_chi=$DX_FLAG_chi
|
||||
#echo DX_FLAG_rtf=$DX_FLAG_rtf
|
||||
#echo DX_FLAG_xml=$DX_FLAG_xml
|
||||
#echo DX_FLAG_pdf=$DX_FLAG_pdf
|
||||
#echo DX_FLAG_ps=$DX_FLAG_ps
|
||||
#echo DX_ENV=$DX_ENV
|
||||
])
|
986
setup/dbaas/redismodule/src/exstrings.c
Executable file
986
setup/dbaas/redismodule/src/exstrings.c
Executable file
@@ -0,0 +1,986 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Nokia.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
* platform project (RICP).
|
||||
*/
|
||||
|
||||
#include "redismodule.h"
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#ifdef __UT__
|
||||
#include "exstringsStub.h"
|
||||
#include "commonStub.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* make sure the response is not NULL or an error.
|
||||
sends the error to the client and exit the current function if its */
|
||||
#define ASSERT_NOERROR(r) \
|
||||
if (r == NULL) { \
|
||||
return RedisModule_ReplyWithError(ctx,"ERR reply is NULL"); \
|
||||
} else if (RedisModule_CallReplyType(r) == REDISMODULE_REPLY_ERROR) { \
|
||||
return RedisModule_ReplyWithCallReply(ctx,r); \
|
||||
}
|
||||
|
||||
#define OBJ_OP_NO 0
|
||||
#define OBJ_OP_XX (1<<1) /* OP if key exist */
|
||||
#define OBJ_OP_NX (1<<2) /* OP if key not exist */
|
||||
#define OBJ_OP_IE (1<<4) /* OP if equal old value */
|
||||
#define OBJ_OP_NE (1<<5) /* OP if not equal old value */
|
||||
|
||||
#define DEF_COUNT 50
|
||||
#define ZERO 0
|
||||
#define MATCH_STR "MATCH"
|
||||
#define COUNT_STR "COUNT"
|
||||
#define SCANARGC 5
|
||||
|
||||
RedisModuleString *def_count_str = NULL, *match_str = NULL, *count_str = NULL, *zero_str = NULL;
|
||||
|
||||
typedef struct _NgetArgs {
|
||||
RedisModuleString *key;
|
||||
RedisModuleString *count;
|
||||
} NgetArgs;
|
||||
|
||||
typedef struct RedisModuleBlockedClientArgs {
|
||||
RedisModuleBlockedClient *bc;
|
||||
NgetArgs nget_args;
|
||||
} RedisModuleBlockedClientArgs;
|
||||
|
||||
void InitStaticVariable()
|
||||
{
|
||||
if (def_count_str == NULL)
|
||||
def_count_str = RedisModule_CreateStringFromLongLong(NULL, DEF_COUNT);
|
||||
if (match_str == NULL)
|
||||
match_str = RedisModule_CreateString(NULL, MATCH_STR, sizeof(MATCH_STR));
|
||||
if (count_str == NULL)
|
||||
count_str = RedisModule_CreateString(NULL, COUNT_STR, sizeof(COUNT_STR));
|
||||
if (zero_str == NULL)
|
||||
zero_str = RedisModule_CreateStringFromLongLong(NULL, ZERO);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int getKeyType(RedisModuleCtx *ctx, RedisModuleString *key_str)
|
||||
{
|
||||
RedisModuleKey *key = RedisModule_OpenKey(ctx, key_str, REDISMODULE_READ);
|
||||
int type = RedisModule_KeyType(key);
|
||||
RedisModule_CloseKey(key);
|
||||
return type;
|
||||
}
|
||||
|
||||
bool replyContentsEqualString(RedisModuleCallReply *reply, RedisModuleString *expected_value)
|
||||
{
|
||||
size_t replylen = 0, expectedlen = 0;
|
||||
const char *expectedval = RedisModule_StringPtrLen(expected_value, &expectedlen);
|
||||
const char *replyval = RedisModule_CallReplyStringPtr(reply, &replylen);
|
||||
return replyval &&
|
||||
expectedlen == replylen &&
|
||||
!strncmp(expectedval, replyval, replylen);
|
||||
}
|
||||
|
||||
typedef struct _SetParams {
|
||||
RedisModuleString **key_val_pairs;
|
||||
size_t length;
|
||||
} SetParams;
|
||||
|
||||
typedef struct _PubParams {
|
||||
RedisModuleString **channel_msg_pairs;
|
||||
size_t length;
|
||||
} PubParams;
|
||||
|
||||
typedef struct _DelParams {
|
||||
RedisModuleString **keys;
|
||||
size_t length;
|
||||
} DelParams;
|
||||
|
||||
typedef enum _ExstringsStatus {
|
||||
EXSTRINGS_STATUS_NO_ERRORS = 0,
|
||||
EXSTRINGS_STATUS_ERROR_AND_REPLY_SENT,
|
||||
EXSTRINGS_STATUS_NOT_SET
|
||||
} ExstringsStatus;
|
||||
|
||||
void readNgetArgs(RedisModuleCtx *ctx, RedisModuleString **argv, int argc,
|
||||
NgetArgs* nget_args, ExstringsStatus* status)
|
||||
{
|
||||
size_t str_len;
|
||||
long long number;
|
||||
|
||||
if(argc == 2) {
|
||||
nget_args->key = argv[1];
|
||||
nget_args->count = def_count_str;
|
||||
} else if (argc == 4) {
|
||||
if (strcasecmp(RedisModule_StringPtrLen(argv[2], &str_len), "count")) {
|
||||
RedisModule_ReplyWithError(ctx,"-ERR syntax error");
|
||||
*status = EXSTRINGS_STATUS_ERROR_AND_REPLY_SENT;
|
||||
return;
|
||||
}
|
||||
|
||||
int ret = RedisModule_StringToLongLong(argv[3], &number) != REDISMODULE_OK;
|
||||
if (ret != REDISMODULE_OK || number < 1) {
|
||||
RedisModule_ReplyWithError(ctx,"-ERR value is not an integer or out of range");
|
||||
*status = EXSTRINGS_STATUS_ERROR_AND_REPLY_SENT;
|
||||
return;
|
||||
}
|
||||
|
||||
nget_args->key = argv[1];
|
||||
nget_args->count = argv[3];
|
||||
} else {
|
||||
/* In redis there is a bug (or undocumented feature see link)
|
||||
* where calling 'RedisModule_WrongArity'
|
||||
* within a blocked client will crash redis.
|
||||
*
|
||||
* Therefore we need to call this function to validate args
|
||||
* before putting the client into blocking mode.
|
||||
*
|
||||
* Link to issue:
|
||||
* https://github.com/antirez/redis/issues/6382
|
||||
* 'If any thread tries to access the command arguments from
|
||||
* within the ThreadSafeContext they will crash redis' */
|
||||
RedisModule_WrongArity(ctx);
|
||||
*status = EXSTRINGS_STATUS_ERROR_AND_REPLY_SENT;
|
||||
return;
|
||||
}
|
||||
|
||||
*status = EXSTRINGS_STATUS_NO_ERRORS;
|
||||
return;
|
||||
}
|
||||
|
||||
long long callReplyLongLong(RedisModuleCallReply* reply)
|
||||
{
|
||||
const char* cursor_str_ptr = RedisModule_CallReplyStringPtr(reply, NULL);
|
||||
return strtoll(cursor_str_ptr, NULL, 10);
|
||||
}
|
||||
|
||||
void forwardIfError(RedisModuleCtx *ctx, RedisModuleCallReply *reply, ExstringsStatus* status)
|
||||
{
|
||||
if (RedisModule_CallReplyType(reply) == REDISMODULE_REPLY_ERROR) {
|
||||
RedisModule_ReplyWithCallReply(ctx, reply);
|
||||
RedisModule_FreeCallReply(reply);
|
||||
*status = EXSTRINGS_STATUS_ERROR_AND_REPLY_SENT;
|
||||
}
|
||||
*status = EXSTRINGS_STATUS_NO_ERRORS;
|
||||
}
|
||||
|
||||
typedef struct _ScannedKeys {
|
||||
RedisModuleString **keys;
|
||||
size_t len;
|
||||
} ScannedKeys;
|
||||
|
||||
ScannedKeys* allocScannedKeys(size_t len)
|
||||
{
|
||||
ScannedKeys *sk = RedisModule_Alloc(sizeof(ScannedKeys));
|
||||
if (sk) {
|
||||
sk->len = len;
|
||||
sk->keys = RedisModule_Alloc(sizeof(RedisModuleString *)*len);
|
||||
}
|
||||
return sk;
|
||||
}
|
||||
|
||||
void freeScannedKeys(RedisModuleCtx *ctx, ScannedKeys* sk)
|
||||
{
|
||||
if (sk) {
|
||||
size_t j;
|
||||
for (j = 0; j < sk->len; j++)
|
||||
RedisModule_FreeString(ctx, sk->keys[j]);
|
||||
RedisModule_Free(sk->keys);
|
||||
}
|
||||
RedisModule_Free(sk);
|
||||
}
|
||||
|
||||
typedef struct _ScanSomeState {
|
||||
RedisModuleString *key;
|
||||
RedisModuleString *count;
|
||||
long long cursor;
|
||||
} ScanSomeState;
|
||||
|
||||
ScannedKeys *scanSome(RedisModuleCtx* ctx, ScanSomeState* state, ExstringsStatus* status)
|
||||
{
|
||||
RedisModuleString *scanargv[SCANARGC] = {NULL};
|
||||
|
||||
scanargv[0] = RedisModule_CreateStringFromLongLong(ctx, state->cursor);
|
||||
scanargv[1] = match_str;
|
||||
scanargv[2] = state->key;
|
||||
scanargv[3] = count_str;
|
||||
scanargv[4] = state->count;
|
||||
|
||||
RedisModuleCallReply *reply;
|
||||
reply = RedisModule_Call(ctx, "SCAN", "v", scanargv, SCANARGC);
|
||||
RedisModule_FreeString(ctx, scanargv[0]);
|
||||
forwardIfError(ctx, reply, status);
|
||||
if (*status == EXSTRINGS_STATUS_ERROR_AND_REPLY_SENT)
|
||||
return NULL;
|
||||
|
||||
state->cursor = callReplyLongLong(RedisModule_CallReplyArrayElement(reply, 0));
|
||||
RedisModuleCallReply *cr_keys =
|
||||
RedisModule_CallReplyArrayElement(reply, 1);
|
||||
|
||||
size_t scanned_keys_len = RedisModule_CallReplyLength(cr_keys);
|
||||
if (scanned_keys_len == 0) {
|
||||
RedisModule_FreeCallReply(reply);
|
||||
*status = EXSTRINGS_STATUS_NO_ERRORS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ScannedKeys *scanned_keys = allocScannedKeys(scanned_keys_len);
|
||||
if (scanned_keys == NULL) {
|
||||
RedisModule_FreeCallReply(reply);
|
||||
RedisModule_ReplyWithError(ctx,"-ERR Out of memory");
|
||||
*status = EXSTRINGS_STATUS_ERROR_AND_REPLY_SENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scanned_keys->len = scanned_keys_len;
|
||||
size_t j;
|
||||
for (j = 0; j < scanned_keys_len; j++) {
|
||||
RedisModuleString *rms = RedisModule_CreateStringFromCallReply(RedisModule_CallReplyArrayElement(cr_keys,j));
|
||||
scanned_keys->keys[j] = rms;
|
||||
}
|
||||
RedisModule_FreeCallReply(reply);
|
||||
*status = EXSTRINGS_STATUS_NO_ERRORS;
|
||||
return scanned_keys;
|
||||
}
|
||||
|
||||
inline void unlockThreadsafeContext(RedisModuleCtx *ctx, bool using_threadsafe_context)
|
||||
{
|
||||
if (using_threadsafe_context)
|
||||
RedisModule_ThreadSafeContextUnlock(ctx);
|
||||
}
|
||||
|
||||
inline void lockThreadsafeContext(RedisModuleCtx *ctx, bool using_threadsafe_context)
|
||||
{
|
||||
if (using_threadsafe_context)
|
||||
RedisModule_ThreadSafeContextLock(ctx);
|
||||
}
|
||||
|
||||
void multiPubCommand(RedisModuleCtx *ctx, PubParams* pubParams)
|
||||
{
|
||||
RedisModuleCallReply *reply = NULL;
|
||||
for (unsigned int i = 0 ; i < pubParams->length ; i += 2) {
|
||||
reply = RedisModule_Call(ctx, "PUBLISH", "v", pubParams->channel_msg_pairs + i, 2);
|
||||
RedisModule_FreeCallReply(reply);
|
||||
}
|
||||
}
|
||||
|
||||
int setStringGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv,
|
||||
int argc, const int flag)
|
||||
{
|
||||
RedisModuleString *oldvalstr = NULL;
|
||||
RedisModuleCallReply *reply = NULL;
|
||||
|
||||
if (argc < 4)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
else
|
||||
oldvalstr = argv[3];
|
||||
|
||||
/*Check if key type is string*/
|
||||
RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1],
|
||||
REDISMODULE_READ);
|
||||
int type = RedisModule_KeyType(key);
|
||||
RedisModule_CloseKey(key);
|
||||
|
||||
if (type == REDISMODULE_KEYTYPE_EMPTY) {
|
||||
if (flag == OBJ_OP_IE){
|
||||
RedisModule_ReplyWithNull(ctx);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
} else if (type != REDISMODULE_KEYTYPE_STRING) {
|
||||
return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE);
|
||||
}
|
||||
|
||||
/*Get the value*/
|
||||
reply = RedisModule_Call(ctx, "GET", "s", argv[1]);
|
||||
ASSERT_NOERROR(reply)
|
||||
size_t curlen=0, oldvallen=0;
|
||||
const char *oldval = RedisModule_StringPtrLen(oldvalstr, &oldvallen);
|
||||
const char *curval = RedisModule_CallReplyStringPtr(reply, &curlen);
|
||||
if (((flag == OBJ_OP_IE) &&
|
||||
(!curval || (oldvallen != curlen) || strncmp(oldval, curval, curlen)))
|
||||
||
|
||||
((flag == OBJ_OP_NE) && curval && (oldvallen == curlen) &&
|
||||
!strncmp(oldval, curval, curlen))) {
|
||||
RedisModule_FreeCallReply(reply);
|
||||
return RedisModule_ReplyWithNull(ctx);
|
||||
}
|
||||
RedisModule_FreeCallReply(reply);
|
||||
|
||||
/* Prepare the arguments for the command. */
|
||||
int i, j=0, cmdargc=argc-2;
|
||||
RedisModuleString *cmdargv[cmdargc];
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (i == 3)
|
||||
continue;
|
||||
cmdargv[j++] = argv[i];
|
||||
}
|
||||
|
||||
/* Call the command and pass back the reply. */
|
||||
reply = RedisModule_Call(ctx, "SET", "v!", cmdargv, cmdargc);
|
||||
ASSERT_NOERROR(reply)
|
||||
RedisModule_ReplyWithCallReply(ctx, reply);
|
||||
|
||||
RedisModule_FreeCallReply(reply);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
int SetIE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
RedisModule_AutoMemory(ctx);
|
||||
return setStringGenericCommand(ctx, argv, argc, OBJ_OP_IE);
|
||||
}
|
||||
|
||||
int SetNE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
RedisModule_AutoMemory(ctx);
|
||||
return setStringGenericCommand(ctx, argv, argc, OBJ_OP_NE);
|
||||
}
|
||||
|
||||
int delStringGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv,
|
||||
int argc, const int flag)
|
||||
{
|
||||
RedisModuleString *oldvalstr = NULL;
|
||||
RedisModuleCallReply *reply = NULL;
|
||||
|
||||
if (argc == 3)
|
||||
oldvalstr = argv[2];
|
||||
else
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
/*Check if key type is string*/
|
||||
RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1],
|
||||
REDISMODULE_READ);
|
||||
int type = RedisModule_KeyType(key);
|
||||
RedisModule_CloseKey(key);
|
||||
|
||||
if (type == REDISMODULE_KEYTYPE_EMPTY) {
|
||||
return RedisModule_ReplyWithLongLong(ctx, 0);
|
||||
} else if (type != REDISMODULE_KEYTYPE_STRING) {
|
||||
return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE);
|
||||
}
|
||||
|
||||
/*Get the value*/
|
||||
reply = RedisModule_Call(ctx, "GET", "s", argv[1]);
|
||||
ASSERT_NOERROR(reply)
|
||||
size_t curlen = 0, oldvallen = 0;
|
||||
const char *oldval = RedisModule_StringPtrLen(oldvalstr, &oldvallen);
|
||||
const char *curval = RedisModule_CallReplyStringPtr(reply, &curlen);
|
||||
if (((flag == OBJ_OP_IE) &&
|
||||
(!curval || (oldvallen != curlen) || strncmp(oldval, curval, curlen)))
|
||||
||
|
||||
((flag == OBJ_OP_NE) && curval && (oldvallen == curlen) &&
|
||||
!strncmp(oldval, curval, curlen))) {
|
||||
RedisModule_FreeCallReply(reply);
|
||||
return RedisModule_ReplyWithLongLong(ctx, 0);
|
||||
}
|
||||
RedisModule_FreeCallReply(reply);
|
||||
|
||||
/* Prepare the arguments for the command. */
|
||||
int cmdargc=1;
|
||||
RedisModuleString *cmdargv[1];
|
||||
cmdargv[0] = argv[1];
|
||||
|
||||
/* Call the command and pass back the reply. */
|
||||
reply = RedisModule_Call(ctx, "UNLINK", "v!", cmdargv, cmdargc);
|
||||
ASSERT_NOERROR(reply)
|
||||
RedisModule_ReplyWithCallReply(ctx, reply);
|
||||
|
||||
RedisModule_FreeCallReply(reply);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
int DelIE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
RedisModule_AutoMemory(ctx);
|
||||
return delStringGenericCommand(ctx, argv, argc, OBJ_OP_IE);
|
||||
}
|
||||
|
||||
int DelNE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
RedisModule_AutoMemory(ctx);
|
||||
return delStringGenericCommand(ctx, argv, argc, OBJ_OP_NE);
|
||||
}
|
||||
int setPubStringCommon(RedisModuleCtx *ctx, SetParams* setParamsPtr, PubParams* pubParamsPtr)
|
||||
{
|
||||
RedisModuleCallReply *setReply;
|
||||
setReply = RedisModule_Call(ctx, "MSET", "v!", setParamsPtr->key_val_pairs, setParamsPtr->length);
|
||||
ASSERT_NOERROR(setReply)
|
||||
multiPubCommand(ctx, pubParamsPtr);
|
||||
RedisModule_ReplyWithCallReply(ctx, setReply);
|
||||
RedisModule_FreeCallReply(setReply);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
int SetPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc < 5 || (argc % 2) == 0)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
RedisModule_AutoMemory(ctx);
|
||||
SetParams setParams = {
|
||||
.key_val_pairs = argv + 1,
|
||||
.length = argc - 3
|
||||
};
|
||||
PubParams pubParams = {
|
||||
.channel_msg_pairs = argv + 1 + setParams.length,
|
||||
.length = 2
|
||||
};
|
||||
|
||||
return setPubStringCommon(ctx, &setParams, &pubParams);
|
||||
}
|
||||
|
||||
int SetMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc < 7 || (argc % 2) == 0)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
RedisModule_AutoMemory(ctx);
|
||||
long long setPairsCount, pubPairsCount;
|
||||
RedisModule_StringToLongLong(argv[1], &setPairsCount);
|
||||
RedisModule_StringToLongLong(argv[2], &pubPairsCount);
|
||||
if (setPairsCount < 1 || pubPairsCount < 1)
|
||||
return RedisModule_ReplyWithError(ctx, "ERR SET_PAIR_COUNT and PUB_PAIR_COUNT must be greater than zero");
|
||||
|
||||
long long setLen, pubLen;
|
||||
setLen = 2*setPairsCount;
|
||||
pubLen = 2*pubPairsCount;
|
||||
|
||||
if (setLen + pubLen + 3 != argc)
|
||||
return RedisModule_ReplyWithError(ctx, "ERR SET_PAIR_COUNT or PUB_PAIR_COUNT do not match the total pair count");
|
||||
|
||||
SetParams setParams = {
|
||||
.key_val_pairs = argv + 3,
|
||||
.length = setLen
|
||||
};
|
||||
PubParams pubParams = {
|
||||
.channel_msg_pairs = argv + 3 + setParams.length,
|
||||
.length = pubLen
|
||||
};
|
||||
|
||||
return setPubStringCommon(ctx, &setParams, &pubParams);
|
||||
}
|
||||
|
||||
int setIENEPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int flag)
|
||||
{
|
||||
SetParams setParams = {
|
||||
.key_val_pairs = argv + 1,
|
||||
.length = 2
|
||||
};
|
||||
PubParams pubParams = {
|
||||
.channel_msg_pairs = argv + 4,
|
||||
.length = argc - 4
|
||||
};
|
||||
RedisModuleString *key = setParams.key_val_pairs[0];
|
||||
RedisModuleString *oldvalstr = argv[3];
|
||||
|
||||
int type = getKeyType(ctx, key);
|
||||
if (flag == OBJ_OP_IE && type == REDISMODULE_KEYTYPE_EMPTY) {
|
||||
return RedisModule_ReplyWithNull(ctx);
|
||||
} else if (type != REDISMODULE_KEYTYPE_STRING && type != REDISMODULE_KEYTYPE_EMPTY) {
|
||||
return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
|
||||
}
|
||||
|
||||
RedisModuleCallReply *reply = RedisModule_Call(ctx, "GET", "s", key);
|
||||
ASSERT_NOERROR(reply)
|
||||
bool is_equal = replyContentsEqualString(reply, oldvalstr);
|
||||
RedisModule_FreeCallReply(reply);
|
||||
if ((flag == OBJ_OP_IE && !is_equal) ||
|
||||
(flag == OBJ_OP_NE && is_equal)) {
|
||||
return RedisModule_ReplyWithNull(ctx);
|
||||
}
|
||||
|
||||
return setPubStringCommon(ctx, &setParams, &pubParams);
|
||||
}
|
||||
|
||||
int SetIEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc != 6)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
RedisModule_AutoMemory(ctx);
|
||||
return setIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE);
|
||||
}
|
||||
|
||||
int SetIEMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc < 6 || (argc % 2) != 0)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
RedisModule_AutoMemory(ctx);
|
||||
return setIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE);
|
||||
}
|
||||
|
||||
int SetNEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc != 6)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
RedisModule_AutoMemory(ctx);
|
||||
return setIENEPubStringCommon(ctx, argv, argc, OBJ_OP_NE);
|
||||
}
|
||||
|
||||
int setXXNXPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int flag)
|
||||
{
|
||||
SetParams setParams = {
|
||||
.key_val_pairs = argv + 1,
|
||||
.length = 2
|
||||
};
|
||||
PubParams pubParams = {
|
||||
.channel_msg_pairs = argv + 3,
|
||||
.length = argc - 3
|
||||
};
|
||||
RedisModuleString *key = setParams.key_val_pairs[0];
|
||||
|
||||
int type = getKeyType(ctx, key);
|
||||
if ((flag == OBJ_OP_XX && type == REDISMODULE_KEYTYPE_EMPTY) ||
|
||||
(flag == OBJ_OP_NX && type == REDISMODULE_KEYTYPE_STRING)) {
|
||||
return RedisModule_ReplyWithNull(ctx);
|
||||
} else if (type != REDISMODULE_KEYTYPE_STRING && type != REDISMODULE_KEYTYPE_EMPTY) {
|
||||
RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
return setPubStringCommon(ctx, &setParams, &pubParams);
|
||||
}
|
||||
|
||||
int SetNXPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc != 5)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
RedisModule_AutoMemory(ctx);
|
||||
return setXXNXPubStringCommon(ctx, argv, argc, OBJ_OP_NX);
|
||||
}
|
||||
|
||||
int SetNXMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc < 5 || (argc % 2) == 0)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
RedisModule_AutoMemory(ctx);
|
||||
return setXXNXPubStringCommon(ctx, argv, argc, OBJ_OP_NX);
|
||||
}
|
||||
|
||||
int SetXXPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc != 5)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
RedisModule_AutoMemory(ctx);
|
||||
return setXXNXPubStringCommon(ctx, argv, argc, OBJ_OP_XX);
|
||||
}
|
||||
|
||||
int delPubStringCommon(RedisModuleCtx *ctx, DelParams *delParamsPtr, PubParams *pubParamsPtr)
|
||||
{
|
||||
RedisModuleCallReply *reply = RedisModule_Call(ctx, "UNLINK", "v!", delParamsPtr->keys, delParamsPtr->length);
|
||||
ASSERT_NOERROR(reply)
|
||||
int replytype = RedisModule_CallReplyType(reply);
|
||||
if (replytype == REDISMODULE_REPLY_NULL) {
|
||||
RedisModule_ReplyWithNull(ctx);
|
||||
} else if (RedisModule_CallReplyInteger(reply) == 0) {
|
||||
RedisModule_ReplyWithCallReply(ctx, reply);
|
||||
} else {
|
||||
RedisModule_ReplyWithCallReply(ctx, reply);
|
||||
multiPubCommand(ctx, pubParamsPtr);
|
||||
}
|
||||
RedisModule_FreeCallReply(reply);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
int DelPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc < 4)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
RedisModule_AutoMemory(ctx);
|
||||
DelParams delParams = {
|
||||
.keys = argv + 1,
|
||||
.length = argc - 3
|
||||
};
|
||||
PubParams pubParams = {
|
||||
.channel_msg_pairs = argv + 1 + delParams.length,
|
||||
.length = 2
|
||||
};
|
||||
|
||||
return delPubStringCommon(ctx, &delParams, &pubParams);
|
||||
}
|
||||
|
||||
int DelMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc < 6)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
RedisModule_AutoMemory(ctx);
|
||||
long long delCount, pubPairsCount;
|
||||
RedisModule_StringToLongLong(argv[1], &delCount);
|
||||
RedisModule_StringToLongLong(argv[2], &pubPairsCount);
|
||||
if (delCount < 1 || pubPairsCount < 1)
|
||||
return RedisModule_ReplyWithError(ctx, "ERR DEL_COUNT and PUB_PAIR_COUNT must be greater than zero");
|
||||
|
||||
long long delLen, pubLen;
|
||||
delLen = delCount;
|
||||
pubLen = 2*pubPairsCount;
|
||||
if (delLen + pubLen + 3 != argc)
|
||||
return RedisModule_ReplyWithError(ctx, "ERR DEL_COUNT or PUB_PAIR_COUNT do not match the total pair count");
|
||||
|
||||
DelParams delParams = {
|
||||
.keys = argv + 3,
|
||||
.length = delLen
|
||||
};
|
||||
PubParams pubParams = {
|
||||
.channel_msg_pairs = argv + 3 + delParams.length,
|
||||
.length = pubLen
|
||||
};
|
||||
|
||||
return delPubStringCommon(ctx, &delParams, &pubParams);
|
||||
}
|
||||
|
||||
int delIENEPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int flag)
|
||||
{
|
||||
DelParams delParams = {
|
||||
.keys = argv + 1,
|
||||
.length = 1
|
||||
};
|
||||
PubParams pubParams = {
|
||||
.channel_msg_pairs = argv + 3,
|
||||
.length = argc - 3
|
||||
};
|
||||
RedisModuleString *key = argv[1];
|
||||
RedisModuleString *oldvalstr = argv[2];
|
||||
|
||||
int type = getKeyType(ctx, key);
|
||||
if (type == REDISMODULE_KEYTYPE_EMPTY) {
|
||||
return RedisModule_ReplyWithLongLong(ctx, 0);
|
||||
} else if (type != REDISMODULE_KEYTYPE_STRING) {
|
||||
return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
|
||||
}
|
||||
|
||||
RedisModuleCallReply *reply = RedisModule_Call(ctx, "GET", "s", key);
|
||||
ASSERT_NOERROR(reply)
|
||||
bool is_equal = replyContentsEqualString(reply, oldvalstr);
|
||||
RedisModule_FreeCallReply(reply);
|
||||
if ((flag == OBJ_OP_IE && !is_equal) ||
|
||||
(flag == OBJ_OP_NE && is_equal)) {
|
||||
return RedisModule_ReplyWithLongLong(ctx, 0);
|
||||
}
|
||||
|
||||
return delPubStringCommon(ctx, &delParams, &pubParams);
|
||||
}
|
||||
|
||||
int DelIEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc != 5)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
RedisModule_AutoMemory(ctx);
|
||||
return delIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE);
|
||||
}
|
||||
|
||||
int DelIEMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc < 5 || (argc % 2) == 0)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
RedisModule_AutoMemory(ctx);
|
||||
return delIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE);
|
||||
}
|
||||
|
||||
int DelNEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
if (argc != 5)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
RedisModule_AutoMemory(ctx);
|
||||
return delIENEPubStringCommon(ctx, argv, argc, OBJ_OP_NE);
|
||||
}
|
||||
|
||||
int Nget_RedisCommand(RedisModuleCtx *ctx, NgetArgs* nget_args, bool using_threadsafe_context)
|
||||
{
|
||||
int ret = REDISMODULE_OK;
|
||||
size_t replylen = 0;
|
||||
RedisModuleCallReply *reply = NULL;
|
||||
ExstringsStatus status = EXSTRINGS_STATUS_NOT_SET;
|
||||
ScanSomeState scan_state;
|
||||
ScannedKeys *scanned_keys;
|
||||
|
||||
scan_state.key = nget_args->key;
|
||||
scan_state.count = nget_args->count;
|
||||
scan_state.cursor = 0;
|
||||
|
||||
RedisModule_ReplyWithArray(ctx, REDISMODULE_POSTPONED_ARRAY_LEN);
|
||||
do {
|
||||
lockThreadsafeContext(ctx, using_threadsafe_context);
|
||||
|
||||
status = EXSTRINGS_STATUS_NOT_SET;
|
||||
scanned_keys = scanSome(ctx, &scan_state, &status);
|
||||
|
||||
if (status != EXSTRINGS_STATUS_NO_ERRORS) {
|
||||
unlockThreadsafeContext(ctx, using_threadsafe_context);
|
||||
ret = REDISMODULE_ERR;
|
||||
break;
|
||||
} else if (scanned_keys == NULL) {
|
||||
unlockThreadsafeContext(ctx, using_threadsafe_context);
|
||||
continue;
|
||||
}
|
||||
|
||||
reply = RedisModule_Call(ctx, "MGET", "v", scanned_keys->keys, scanned_keys->len);
|
||||
|
||||
unlockThreadsafeContext(ctx, using_threadsafe_context);
|
||||
|
||||
status = EXSTRINGS_STATUS_NOT_SET;
|
||||
forwardIfError(ctx, reply, &status);
|
||||
if (status != EXSTRINGS_STATUS_NO_ERRORS) {
|
||||
freeScannedKeys(ctx, scanned_keys);
|
||||
ret = REDISMODULE_ERR;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < scanned_keys->len; i++) {
|
||||
RedisModuleString *rms = RedisModule_CreateStringFromCallReply(RedisModule_CallReplyArrayElement(reply, i));
|
||||
if (rms) {
|
||||
RedisModule_ReplyWithString(ctx, scanned_keys->keys[i]);
|
||||
RedisModule_ReplyWithString(ctx, rms);
|
||||
RedisModule_FreeString(ctx, rms);
|
||||
replylen += 2;
|
||||
}
|
||||
}
|
||||
RedisModule_FreeCallReply(reply);
|
||||
freeScannedKeys(ctx, scanned_keys);
|
||||
} while (scan_state.cursor != 0);
|
||||
|
||||
RedisModule_ReplySetArrayLength(ctx,replylen);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The thread entry point that actually executes the blocking part
|
||||
* of the command nget.noatomic
|
||||
*/
|
||||
void *NGet_NoAtomic_ThreadMain(void *arg)
|
||||
{
|
||||
pthread_detach(pthread_self());
|
||||
|
||||
RedisModuleBlockedClientArgs *bca = arg;
|
||||
RedisModuleBlockedClient *bc = bca->bc;
|
||||
RedisModuleCtx *ctx = RedisModule_GetThreadSafeContext(bc);
|
||||
|
||||
Nget_RedisCommand(ctx, &bca->nget_args, true);
|
||||
RedisModule_FreeThreadSafeContext(ctx);
|
||||
RedisModule_UnblockClient(bc, NULL);
|
||||
RedisModule_Free(bca);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int NGet_NoAtomic_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
RedisModule_AutoMemory(ctx);
|
||||
pthread_t tid;
|
||||
|
||||
InitStaticVariable();
|
||||
|
||||
RedisModuleBlockedClientArgs *bca = RedisModule_Alloc(sizeof(RedisModuleBlockedClientArgs));
|
||||
if (bca == NULL) {
|
||||
RedisModule_ReplyWithError(ctx,"-ERR Out of memory");
|
||||
return REDISMODULE_ERR;
|
||||
}
|
||||
|
||||
ExstringsStatus status = EXSTRINGS_STATUS_NOT_SET;
|
||||
readNgetArgs(ctx, argv, argc, &bca->nget_args, &status);
|
||||
if (status != EXSTRINGS_STATUS_NO_ERRORS) {
|
||||
RedisModule_Free(bca);
|
||||
return REDISMODULE_ERR;
|
||||
}
|
||||
|
||||
/* Note that when blocking the client we do not set any callback: no
|
||||
* timeout is possible since we passed '0', nor we need a reply callback
|
||||
* because we'll use the thread safe context to accumulate a reply. */
|
||||
RedisModuleBlockedClient *bc = RedisModule_BlockClient(ctx,NULL,NULL,NULL,0);
|
||||
|
||||
bca->bc = bc;
|
||||
|
||||
/* Now that we setup a blocking client, we need to pass the control
|
||||
* to the thread. However we need to pass arguments to the thread:
|
||||
* the reference to the blocked client handle. */
|
||||
if (pthread_create(&tid,NULL,NGet_NoAtomic_ThreadMain,bca) != 0) {
|
||||
RedisModule_AbortBlock(bc);
|
||||
RedisModule_Free(bca);
|
||||
return RedisModule_ReplyWithError(ctx,"-ERR Can't start thread");
|
||||
}
|
||||
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
int NGet_Atomic_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
RedisModule_AutoMemory(ctx);
|
||||
NgetArgs nget_args;
|
||||
ExstringsStatus status = EXSTRINGS_STATUS_NOT_SET;
|
||||
|
||||
InitStaticVariable();
|
||||
|
||||
readNgetArgs(ctx, argv, argc, &nget_args, &status);
|
||||
if (status != EXSTRINGS_STATUS_NO_ERRORS) {
|
||||
return REDISMODULE_ERR;
|
||||
}
|
||||
|
||||
return Nget_RedisCommand(ctx, &nget_args, false);
|
||||
}
|
||||
|
||||
int NDel_Atomic_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
{
|
||||
RedisModule_AutoMemory(ctx);
|
||||
int ret = REDISMODULE_OK;
|
||||
long long replylen = 0;
|
||||
RedisModuleCallReply *reply = NULL;
|
||||
ExstringsStatus status = EXSTRINGS_STATUS_NOT_SET;
|
||||
ScanSomeState scan_state;
|
||||
ScannedKeys *scanned_keys = NULL;
|
||||
|
||||
InitStaticVariable();
|
||||
if (argc != 2)
|
||||
return RedisModule_WrongArity(ctx);
|
||||
|
||||
scan_state.key = argv[1];
|
||||
scan_state.count = def_count_str;
|
||||
scan_state.cursor = 0;
|
||||
|
||||
do {
|
||||
status = EXSTRINGS_STATUS_NOT_SET;
|
||||
scanned_keys = scanSome(ctx, &scan_state, &status);
|
||||
|
||||
if (status != EXSTRINGS_STATUS_NO_ERRORS) {
|
||||
ret = REDISMODULE_ERR;
|
||||
break;
|
||||
} else if (scanned_keys == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
reply = RedisModule_Call(ctx, "UNLINK", "v!", scanned_keys->keys, scanned_keys->len);
|
||||
|
||||
status = EXSTRINGS_STATUS_NOT_SET;
|
||||
forwardIfError(ctx, reply, &status);
|
||||
if (status != EXSTRINGS_STATUS_NO_ERRORS) {
|
||||
freeScannedKeys(ctx, scanned_keys);
|
||||
ret = REDISMODULE_ERR;
|
||||
break;
|
||||
}
|
||||
|
||||
replylen += RedisModule_CallReplyInteger(reply);
|
||||
RedisModule_FreeCallReply(reply);
|
||||
freeScannedKeys(ctx, scanned_keys);
|
||||
} while (scan_state.cursor != 0);
|
||||
|
||||
if (ret == REDISMODULE_OK) {
|
||||
RedisModule_ReplyWithLongLong(ctx, replylen);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function must be present on each Redis module. It is used in order to
|
||||
* register the commands into the Redis server. */
|
||||
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
||||
REDISMODULE_NOT_USED(argv);
|
||||
REDISMODULE_NOT_USED(argc);
|
||||
|
||||
if (RedisModule_Init(ctx,"exstrings",1,REDISMODULE_APIVER_1)
|
||||
== REDISMODULE_ERR) return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"setie",
|
||||
SetIE_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"setne",
|
||||
SetNE_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"delie",
|
||||
DelIE_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"delne",
|
||||
DelNE_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"nget.atomic",
|
||||
NGet_Atomic_RedisCommand,"readonly",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"nget.noatomic",
|
||||
NGet_NoAtomic_RedisCommand,"readonly",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"ndel.atomic",
|
||||
NDel_Atomic_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"msetpub",
|
||||
SetPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"msetmpub",
|
||||
SetMPub_RedisCommand,"write deny-oom pubsub",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"setiepub",
|
||||
SetIEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"setiempub",
|
||||
SetIEMPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"setnepub",
|
||||
SetNEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"setxxpub",
|
||||
SetXXPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"setnxpub",
|
||||
SetNXPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"setnxmpub",
|
||||
SetNXMPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"delpub",
|
||||
DelPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"delmpub",
|
||||
DelMPub_RedisCommand,"write deny-oom pubsub",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"deliepub",
|
||||
DelIEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"deliempub",
|
||||
DelIEMPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"delnepub",
|
||||
DelNEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
return REDISMODULE_OK;
|
||||
}
|
37
setup/dbaas/redismodule/tst/include/ut_helpers.hpp
Normal file
37
setup/dbaas/redismodule/tst/include/ut_helpers.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Nokia.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
* platform project (RICP).
|
||||
*/
|
||||
|
||||
#ifndef EXSTRING_UT_HELPERS_H_
|
||||
#define EXSTRING_UT_HELPERS_H_
|
||||
|
||||
extern "C" {
|
||||
#include "exstringsStub.h"
|
||||
#include "redismodule.h"
|
||||
}
|
||||
|
||||
#define UT_DUMMY_BUFFER_SIZE 1
|
||||
#define UT_DUMMY_PTR_ADDRESS 1234
|
||||
|
||||
RedisModuleString **createRedisStrVec(size_t size);
|
||||
|
||||
void returnNKeysFromScanSome(long keys);
|
||||
|
||||
#endif
|
37
setup/dbaas/redismodule/tst/mock/include/commonStub.h
Normal file
37
setup/dbaas/redismodule/tst/mock/include/commonStub.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Nokia.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
* platform project (RICP).
|
||||
*/
|
||||
|
||||
#ifndef COMMONSTUB_H_
|
||||
#define COMMONSTUB_H_
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define UT_DUMMY_THREAD_ID 1234
|
||||
|
||||
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*start_routine) (void *), void *arg);
|
||||
|
||||
int pthread_detach(pthread_t thread);
|
||||
|
||||
pthread_t pthread_self(void);
|
||||
|
||||
#endif
|
53
setup/dbaas/redismodule/tst/mock/include/exstringsStub.h
Executable file
53
setup/dbaas/redismodule/tst/mock/include/exstringsStub.h
Executable file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Nokia.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
* platform project (RICP).
|
||||
*/
|
||||
|
||||
#ifndef EXSTRINGSTUB_H_
|
||||
#define EXSTRINGSTUB_H_
|
||||
|
||||
|
||||
#include "redismodule.h"
|
||||
|
||||
int setStringGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, const int flag);
|
||||
int SetIE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int SetNE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) ;
|
||||
int delStringGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, const int flag);
|
||||
int DelIE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int DelNE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int SetPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int SetMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int SetIEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int SetIEMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int SetNEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int SetNXPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int SetNXMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int SetXXPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int DelPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int DelMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int DelIEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int DelIEMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int DelNEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int NDel_Atomic_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int NGet_Atomic_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
int NGet_NoAtomic_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
void *NGet_NoAtomic_ThreadMain(void *arg);
|
||||
|
||||
#endif
|
126
setup/dbaas/redismodule/tst/mock/include/redismodule.h
Executable file
126
setup/dbaas/redismodule/tst/mock/include/redismodule.h
Executable file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Nokia.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
* platform project (RICP).
|
||||
*/
|
||||
|
||||
#ifndef REDISMODULE_H
|
||||
#define REDISMODULE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Error status return values. */
|
||||
#define REDISMODULE_OK 0
|
||||
#define REDISMODULE_ERR 1
|
||||
|
||||
/* API versions. */
|
||||
#define REDISMODULE_APIVER_1 1
|
||||
|
||||
/* API flags and constants */
|
||||
#define REDISMODULE_READ (1<<0)
|
||||
#define REDISMODULE_WRITE (1<<1)
|
||||
|
||||
/* Key types. */
|
||||
#define REDISMODULE_KEYTYPE_EMPTY 0
|
||||
#define REDISMODULE_KEYTYPE_STRING 1
|
||||
#define REDISMODULE_KEYTYPE_LIST 2
|
||||
#define REDISMODULE_KEYTYPE_HASH 3
|
||||
#define REDISMODULE_KEYTYPE_SET 4
|
||||
#define REDISMODULE_KEYTYPE_ZSET 5
|
||||
#define REDISMODULE_KEYTYPE_MODULE 6
|
||||
|
||||
/* Reply types. */
|
||||
#define REDISMODULE_REPLY_UNKNOWN -1
|
||||
#define REDISMODULE_REPLY_STRING 0
|
||||
#define REDISMODULE_REPLY_ERROR 1
|
||||
#define REDISMODULE_REPLY_INTEGER 2
|
||||
#define REDISMODULE_REPLY_ARRAY 3
|
||||
#define REDISMODULE_REPLY_NULL 4
|
||||
|
||||
/* Postponed array length. */
|
||||
#define REDISMODULE_POSTPONED_ARRAY_LEN -1
|
||||
|
||||
/* Error messages. */
|
||||
#define REDISMODULE_ERRORMSG_WRONGTYPE "WRONGTYPE Operation against a key holding the wrong kind of value"
|
||||
|
||||
#define REDISMODULE_NOT_USED(V) ((void) V)
|
||||
|
||||
typedef long long mstime_t;
|
||||
|
||||
/* UT dummy definitions for opaque redis types */
|
||||
typedef struct { int dummy; } RedisModuleCtx;
|
||||
typedef struct { int dummy; } RedisModuleKey;
|
||||
typedef struct { int dummy; } RedisModuleString;
|
||||
typedef struct { int dummy; } RedisModuleCallReply;
|
||||
typedef struct { int dummy; } RedisModuleIO;
|
||||
typedef struct { int dummy; } RedisModuleType;
|
||||
typedef struct { int dummy; } RedisModuleDigest;
|
||||
typedef struct { int dummy; } RedisModuleBlockedClient;
|
||||
|
||||
typedef void *(*RedisModuleTypeLoadFunc)(RedisModuleIO *rdb, int encver);
|
||||
typedef void (*RedisModuleTypeSaveFunc)(RedisModuleIO *rdb, void *value);
|
||||
typedef void (*RedisModuleTypeRewriteFunc)(RedisModuleIO *aof, RedisModuleString *key, void *value);
|
||||
typedef size_t (*RedisModuleTypeMemUsageFunc)(const void *value);
|
||||
typedef void (*RedisModuleTypeDigestFunc)(RedisModuleDigest *digest, void *value);
|
||||
typedef void (*RedisModuleTypeFreeFunc)(void *value);
|
||||
|
||||
typedef int (*RedisModuleCmdFunc) (RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
|
||||
int RedisModule_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep);
|
||||
int RedisModule_WrongArity(RedisModuleCtx *ctx);
|
||||
int RedisModule_ReplyWithLongLong(RedisModuleCtx *ctx, long long ll);
|
||||
void *RedisModule_OpenKey(RedisModuleCtx *ctx, RedisModuleString *keyname, int mode);
|
||||
RedisModuleCallReply *RedisModule_Call(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...);
|
||||
void RedisModule_FreeCallReply(RedisModuleCallReply *reply);
|
||||
int RedisModule_CallReplyType(RedisModuleCallReply *reply);
|
||||
long long RedisModule_CallReplyInteger(RedisModuleCallReply *reply);
|
||||
const char *RedisModule_StringPtrLen(const RedisModuleString *str, size_t *len);
|
||||
int RedisModule_ReplyWithError(RedisModuleCtx *ctx, const char *err);
|
||||
int RedisModule_ReplyWithString(RedisModuleCtx *ctx, RedisModuleString *str);
|
||||
int RedisModule_ReplyWithNull(RedisModuleCtx *ctx);
|
||||
int RedisModule_ReplyWithCallReply(RedisModuleCtx *ctx, RedisModuleCallReply *reply);
|
||||
const char *RedisModule_CallReplyStringPtr(RedisModuleCallReply *reply, size_t *len);
|
||||
RedisModuleString *RedisModule_CreateStringFromCallReply(RedisModuleCallReply *reply);
|
||||
|
||||
int RedisModule_KeyType(RedisModuleKey *kp);
|
||||
void RedisModule_CloseKey(RedisModuleKey *kp);
|
||||
|
||||
int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver);
|
||||
|
||||
size_t RedisModule_CallReplyLength(RedisModuleCallReply *reply);
|
||||
RedisModuleCallReply *RedisModule_CallReplyArrayElement(RedisModuleCallReply *reply, size_t idx);
|
||||
int RedisModule_ReplyWithArray(RedisModuleCtx *ctx, long len);
|
||||
void RedisModule_FreeString(RedisModuleCtx *ctx, RedisModuleString *str);
|
||||
RedisModuleBlockedClient *RedisModule_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms);
|
||||
int RedisModule_UnblockClient(RedisModuleBlockedClient *bc, void *privdata);
|
||||
int RedisModule_AbortBlock(RedisModuleBlockedClient *bc);
|
||||
RedisModuleString *RedisModule_CreateString(RedisModuleCtx *ctx, const char *ptr, size_t len);
|
||||
void RedisModule_FreeThreadSafeContext(RedisModuleCtx *ctx);
|
||||
int RedisModule_StringToLongLong(const RedisModuleString *str, long long *ll);
|
||||
void RedisModule_ThreadSafeContextLock(RedisModuleCtx *ctx);
|
||||
void RedisModule_ThreadSafeContextUnlock(RedisModuleCtx *ctx);
|
||||
void RedisModule_ReplySetArrayLength(RedisModuleCtx *ctx, long len);
|
||||
RedisModuleCtx *RedisModule_GetThreadSafeContext(RedisModuleBlockedClient *bc);
|
||||
RedisModuleString *RedisModule_CreateStringFromLongLong(RedisModuleCtx *ctx, long long ll);
|
||||
void RedisModule_AutoMemory(RedisModuleCtx *ctx);
|
||||
void *RedisModule_Alloc(size_t bytes);
|
||||
void RedisModule_Free(void *ptr);
|
||||
|
||||
#endif /* REDISMODULE_H */
|
76
setup/dbaas/redismodule/tst/mock/src/commonStub.cpp
Normal file
76
setup/dbaas/redismodule/tst/mock/src/commonStub.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Nokia.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
* platform project (RICP).
|
||||
*/
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
extern "C" {
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "redismodule.h"
|
||||
#include "commonStub.h"
|
||||
}
|
||||
|
||||
#include <CppUTest/TestHarness.h>
|
||||
#include <CppUTestExt/MockSupport.h>
|
||||
#include <CppUTest/MemoryLeakDetectorMallocMacros.h>
|
||||
|
||||
typedef struct RedisModuleBlockedClientArgs {
|
||||
RedisModuleBlockedClient *bc;
|
||||
RedisModuleString **argv;
|
||||
int argc;
|
||||
} RedisModuleBlockedClientArgs;
|
||||
|
||||
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*start_routine) (void *), void *arg)
|
||||
{
|
||||
(void)thread;
|
||||
(void)attr;
|
||||
(void)start_routine;
|
||||
if (mock().getData("pthread_create_free_block_client_args").getIntValue()) {
|
||||
RedisModuleBlockedClientArgs* bca = (RedisModuleBlockedClientArgs*)arg;
|
||||
free(bca->bc);
|
||||
free(bca);
|
||||
}
|
||||
|
||||
return mock()
|
||||
.actualCall("pthread_create")
|
||||
.returnIntValueOrDefault(0);
|
||||
}
|
||||
|
||||
int pthread_detach(pthread_t thread)
|
||||
{
|
||||
(void)thread;
|
||||
|
||||
return mock()
|
||||
.actualCall("pthread_detach")
|
||||
.returnIntValueOrDefault(0);
|
||||
}
|
||||
|
||||
pthread_t pthread_self(void)
|
||||
{
|
||||
return mock()
|
||||
.actualCall("pthread_self")
|
||||
.returnIntValueOrDefault(UT_DUMMY_THREAD_ID);
|
||||
}
|
360
setup/dbaas/redismodule/tst/mock/src/redismoduleNewStub.cpp
Executable file
360
setup/dbaas/redismodule/tst/mock/src/redismoduleNewStub.cpp
Executable file
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Nokia.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
* platform project (RICP).
|
||||
*/
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
extern "C" {
|
||||
#include "redismodule.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
}
|
||||
|
||||
#include <CppUTest/TestHarness.h>
|
||||
#include <CppUTestExt/MockSupport.h>
|
||||
|
||||
#include "ut_helpers.hpp"
|
||||
|
||||
RedisModuleCallReply *RedisModule_Call(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)fmt;
|
||||
return (RedisModuleCallReply *)mock().actualCall("RedisModule_Call")
|
||||
.withParameter("cmdname", cmdname)
|
||||
.returnPointerValueOrDefault(malloc(UT_DUMMY_BUFFER_SIZE));
|
||||
}
|
||||
|
||||
int RedisModule_ReplyWithString(RedisModuleCtx *ctx, RedisModuleString *str)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)str;
|
||||
return mock()
|
||||
.actualCall("RedisModule_ReplyWithString")
|
||||
.returnIntValueOrDefault(REDISMODULE_OK);
|
||||
}
|
||||
|
||||
RedisModuleString *RedisModule_CreateStringFromCallReply(RedisModuleCallReply *reply)
|
||||
{
|
||||
(void)reply;
|
||||
return (RedisModuleString *)mock().actualCall("RedisModule_CreateStringFromCallReply")
|
||||
.returnPointerValue();
|
||||
}
|
||||
|
||||
void RedisModule_CloseKey(RedisModuleKey *kp)
|
||||
{
|
||||
(void)kp;
|
||||
mock().actualCall("RedisModule_CloseKey");
|
||||
}
|
||||
|
||||
size_t RedisModule_CallReplyLength(RedisModuleCallReply *reply)
|
||||
{
|
||||
(void)reply;
|
||||
return (size_t)mock().actualCall("RedisModule_CallReplyLength")
|
||||
.returnIntValue();
|
||||
}
|
||||
|
||||
int RedisModule_ReplyWithArray(RedisModuleCtx *ctx, long len)
|
||||
{
|
||||
(void)ctx;
|
||||
return (int)mock().actualCall("RedisModule_ReplyWithArray")
|
||||
.withParameter("len", len)
|
||||
.returnIntValueOrDefault(REDISMODULE_OK);
|
||||
}
|
||||
|
||||
void RedisModule_ReplySetArrayLength(RedisModuleCtx *ctx, long len)
|
||||
{
|
||||
(void)ctx;
|
||||
mock().actualCall("RedisModule_ReplySetArrayLength")
|
||||
.withParameter("len", len);
|
||||
}
|
||||
|
||||
RedisModuleString *RedisModule_CreateString(RedisModuleCtx *ctx, const char *ptr, size_t len)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)ptr;
|
||||
(void)len;
|
||||
void* buf = malloc(UT_DUMMY_BUFFER_SIZE);
|
||||
return (RedisModuleString *) mock()
|
||||
.actualCall("RedisModule_CreateString")
|
||||
.returnPointerValueOrDefault(buf);
|
||||
}
|
||||
|
||||
RedisModuleString *RedisModule_CreateStringFromLongLong(RedisModuleCtx *ctx, long long ll)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)ll;
|
||||
void* buf = malloc(UT_DUMMY_BUFFER_SIZE);
|
||||
return (RedisModuleString *)mock()
|
||||
.actualCall("RedisModule_CreateStringFromLongLong")
|
||||
.returnPointerValueOrDefault(buf);
|
||||
}
|
||||
|
||||
void RedisModule_AutoMemory(RedisModuleCtx *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
mock().actualCall("RedisModule_AutoMemory");
|
||||
}
|
||||
|
||||
void RedisModule_FreeString(RedisModuleCtx *ctx, RedisModuleString *str)
|
||||
{
|
||||
(void)ctx;
|
||||
free(str);
|
||||
mock().actualCall("RedisModule_FreeString");
|
||||
}
|
||||
|
||||
int RedisModule_StringToLongLong(const RedisModuleString *str, long long *ll)
|
||||
{
|
||||
(void)str;
|
||||
return (int)mock().actualCall("RedisModule_StringToLongLong")
|
||||
.withOutputParameter("ll", ll)
|
||||
.returnIntValueOrDefault(REDISMODULE_OK);
|
||||
}
|
||||
|
||||
void RedisModule_FreeCallReply(RedisModuleCallReply *reply)
|
||||
{
|
||||
free(reply);
|
||||
mock().actualCall("RedisModule_FreeCallReply");
|
||||
}
|
||||
|
||||
RedisModuleCallReply *RedisModule_CallReplyArrayElement(RedisModuleCallReply *reply, size_t idx)
|
||||
{
|
||||
(void)reply;
|
||||
(void)idx;
|
||||
return (RedisModuleCallReply *)mock()
|
||||
.actualCall("RedisModule_CallReplyArrayElement")
|
||||
.returnPointerValueOrDefault(NULL);
|
||||
}
|
||||
|
||||
int RedisModule_ReplyWithLongLong(RedisModuleCtx *ctx, long long ll)
|
||||
{
|
||||
(void)ctx;
|
||||
return (int)mock()
|
||||
.actualCall("RedisModule_ReplyWithLongLong")
|
||||
.withParameter("ll", (int)ll)
|
||||
.returnIntValueOrDefault(REDISMODULE_OK);
|
||||
}
|
||||
|
||||
long long RedisModule_CallReplyInteger(RedisModuleCallReply *reply)
|
||||
{
|
||||
(void)reply;
|
||||
return (long long)mock()
|
||||
.actualCall("RedisModule_CallReplyInteger")
|
||||
.returnIntValue();
|
||||
}
|
||||
|
||||
int RedisModule_CallReplyType(RedisModuleCallReply *reply)
|
||||
{
|
||||
(void)reply;
|
||||
return (int)mock()
|
||||
.actualCall("RedisModule_CallReplyType")
|
||||
.returnIntValue();
|
||||
}
|
||||
|
||||
int RedisModule_WrongArity(RedisModuleCtx *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
return (int)mock()
|
||||
.actualCall("RedisModule_WrongArity")
|
||||
.returnIntValueOrDefault(REDISMODULE_ERR);
|
||||
}
|
||||
|
||||
int RedisModule_ReplyWithError(RedisModuleCtx *ctx, const char *err)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)err;
|
||||
return (int)mock()
|
||||
.actualCall("RedisModule_ReplyWithError")
|
||||
.returnIntValueOrDefault(REDISMODULE_OK);
|
||||
}
|
||||
|
||||
int RedisModule_ReplyWithCallReply(RedisModuleCtx *ctx, RedisModuleCallReply *reply)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)reply;
|
||||
return (int)mock()
|
||||
.actualCall("RedisModule_ReplyWithCallReply")
|
||||
.returnIntValueOrDefault(REDISMODULE_OK);
|
||||
}
|
||||
|
||||
void *RedisModule_OpenKey(RedisModuleCtx *ctx, RedisModuleString *keyname, int mode)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)keyname;
|
||||
(void)mode;
|
||||
return (void *)mock()
|
||||
.actualCall("RedisModule_OpenKey")
|
||||
.returnPointerValue();
|
||||
}
|
||||
|
||||
int RedisModule_KeyType(RedisModuleKey *kp)
|
||||
{
|
||||
(void)kp;
|
||||
return (int)mock()
|
||||
.actualCall("RedisModule_KeyType")
|
||||
.returnIntValue();
|
||||
}
|
||||
|
||||
const char *RedisModule_StringPtrLen(const RedisModuleString *str, size_t *len)
|
||||
{
|
||||
(void)str;
|
||||
if (len != NULL) {
|
||||
return (const char *)mock()
|
||||
.actualCall("RedisModule_StringPtrLen")
|
||||
.withOutputParameter("len", len)
|
||||
.returnPointerValue();
|
||||
} else {
|
||||
return (const char *)mock()
|
||||
.actualCall("RedisModule_StringPtrLen")
|
||||
.returnPointerValue();
|
||||
}
|
||||
}
|
||||
|
||||
RedisModuleBlockedClient *RedisModule_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback,
|
||||
RedisModuleCmdFunc timeout_callback,
|
||||
void (*free_privdata)(RedisModuleCtx*,void*),
|
||||
long long timeout_ms)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)reply_callback;
|
||||
(void)timeout_callback;
|
||||
(void)free_privdata;
|
||||
(void)timeout_ms;
|
||||
|
||||
void *buf = malloc(UT_DUMMY_BUFFER_SIZE);
|
||||
return (RedisModuleBlockedClient *)mock()
|
||||
.actualCall("RedisModule_BlockClient")
|
||||
.returnPointerValueOrDefault(buf);
|
||||
}
|
||||
|
||||
int RedisModule_UnblockClient(RedisModuleBlockedClient *bc, void *privdata)
|
||||
{
|
||||
(void)privdata;
|
||||
|
||||
free(bc);
|
||||
return (int)mock()
|
||||
.actualCall("RedisModule_UnblockClient")
|
||||
.returnIntValueOrDefault(REDISMODULE_OK);
|
||||
}
|
||||
|
||||
const char *RedisModule_CallReplyStringPtr(RedisModuleCallReply *reply, size_t *len)
|
||||
{
|
||||
(void)reply;
|
||||
(void)len;
|
||||
|
||||
static char cursor_zero_literal[] = "0";
|
||||
return (const char *)mock()
|
||||
.actualCall("RedisModule_CallReplyStringPtr")
|
||||
.returnPointerValueOrDefault(cursor_zero_literal);
|
||||
}
|
||||
|
||||
int RedisModule_AbortBlock(RedisModuleBlockedClient *bc)
|
||||
{
|
||||
free(bc);
|
||||
return mock()
|
||||
.actualCall("RedisModule_AbortBlock")
|
||||
.returnIntValueOrDefault(REDISMODULE_OK);
|
||||
}
|
||||
|
||||
int RedisModule_ReplyWithNull(RedisModuleCtx *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
return mock()
|
||||
.actualCall("RedisModule_ReplyWithNull")
|
||||
.returnIntValueOrDefault(REDISMODULE_OK);
|
||||
}
|
||||
|
||||
void RedisModule_ThreadSafeContextUnlock(RedisModuleCtx *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
int tmp = mock().getData("TimesThreadSafeContextWasUnlocked").getIntValue();
|
||||
mock().setData("TimesThreadSafeContextWasUnlocked", tmp + 1);
|
||||
mock()
|
||||
.actualCall("RedisModule_ThreadSafeContextUnlock");
|
||||
}
|
||||
|
||||
void RedisModule_ThreadSafeContextLock(RedisModuleCtx *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
int tmp = mock().getData("TimesThreadSafeContextWasLocked").getIntValue();
|
||||
mock().setData("TimesThreadSafeContextWasLocked", tmp + 1);
|
||||
mock()
|
||||
.actualCall("RedisModule_ThreadSafeContextLock");
|
||||
}
|
||||
|
||||
RedisModuleCtx *RedisModule_GetThreadSafeContext(RedisModuleBlockedClient *bc)
|
||||
{
|
||||
(void)bc;
|
||||
return (RedisModuleCtx *)mock()
|
||||
.actualCall("RedisModule_GetThreadSafeContext")
|
||||
.returnPointerValueOrDefault(0);
|
||||
}
|
||||
|
||||
void RedisModule_FreeThreadSafeContext(RedisModuleCtx *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
mock()
|
||||
.actualCall("RedisModule_FreeThreadSafeContext");
|
||||
}
|
||||
|
||||
/* This is included inline inside each Redis module. */
|
||||
int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)name;
|
||||
(void)ver;
|
||||
(void)apiver;
|
||||
|
||||
return mock()
|
||||
.actualCall("RedisModule_Init")
|
||||
.returnIntValueOrDefault(REDISMODULE_OK);
|
||||
}
|
||||
|
||||
int RedisModule_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)name;
|
||||
(void)cmdfunc;
|
||||
(void)strflags;
|
||||
(void)firstkey;
|
||||
(void)lastkey;
|
||||
(void)keystep;
|
||||
|
||||
return mock()
|
||||
.actualCall("RedisModule_CreateCommand")
|
||||
.returnIntValueOrDefault(REDISMODULE_OK);
|
||||
}
|
||||
|
||||
void *RedisModule_Alloc(size_t bytes)
|
||||
{
|
||||
void *buf = malloc(bytes);
|
||||
return mock()
|
||||
.actualCall("RedisModule_Alloc")
|
||||
.returnPointerValueOrDefault(buf);
|
||||
}
|
||||
|
||||
void RedisModule_Free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
mock()
|
||||
.actualCall("RedisModule_Free");
|
||||
}
|
437
setup/dbaas/redismodule/tst/mock/src/redismoduleStub.cpp
Executable file
437
setup/dbaas/redismodule/tst/mock/src/redismoduleStub.cpp
Executable file
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Nokia.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
* platform project (RICP).
|
||||
*/
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
extern "C" {
|
||||
#include "redismodule.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
}
|
||||
|
||||
#include <CppUTest/TestHarness.h>
|
||||
#include <CppUTestExt/MockSupport.h>
|
||||
|
||||
|
||||
int RedisModule_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)name;
|
||||
(void)cmdfunc;
|
||||
(void)strflags;
|
||||
(void)firstkey;
|
||||
(void)lastkey;
|
||||
(void)keystep;
|
||||
return REDISMODULE_OK;
|
||||
|
||||
}
|
||||
|
||||
int RedisModule_WrongArity(RedisModuleCtx *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
mock().setData("RedisModule_WrongArity", 1);
|
||||
return REDISMODULE_ERR;
|
||||
}
|
||||
|
||||
int RedisModule_ReplyWithLongLong(RedisModuleCtx *ctx, long long ll)
|
||||
{
|
||||
|
||||
(void)ctx;
|
||||
mock().setData("RedisModule_ReplyWithLongLong", (int)ll);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
void *RedisModule_OpenKey(RedisModuleCtx *ctx, RedisModuleString *keyname, int mode)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)keyname;
|
||||
(void)mode;
|
||||
|
||||
if (mock().hasData("RedisModule_OpenKey_no"))
|
||||
{
|
||||
return (void*)(0);
|
||||
}
|
||||
|
||||
if (mock().hasData("RedisModule_OpenKey_have"))
|
||||
{
|
||||
return (void*)(111111);
|
||||
}
|
||||
|
||||
|
||||
return (void*)(0);
|
||||
}
|
||||
|
||||
RedisModuleCallReply *RedisModule_Call(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)cmdname;
|
||||
(void)fmt;
|
||||
|
||||
if (!strcmp(cmdname, "GET"))
|
||||
mock().setData("GET", 1);
|
||||
else if (!strcmp(cmdname, "SET"))
|
||||
mock().setData("SET", 1);
|
||||
else if (!strcmp(cmdname, "MSET"))
|
||||
mock().setData("MSET", 1);
|
||||
else if (!strcmp(cmdname, "DEL"))
|
||||
mock().setData("DEL", 1);
|
||||
else if (!strcmp(cmdname, "UNLINK"))
|
||||
mock().setData("UNLINK", 1);
|
||||
else if (!strcmp(cmdname, "PUBLISH"))
|
||||
mock().setData("PUBLISH", mock().getData("PUBLISH").getIntValue() + 1);
|
||||
else if (!strcmp(cmdname, "KEYS"))
|
||||
mock().setData("KEYS", 1);
|
||||
else if (!strcmp(cmdname, "MGET"))
|
||||
mock().setData("MGET", 1);
|
||||
else if (!strcmp(cmdname, "SCAN"))
|
||||
mock().setData("SCAN", 1);
|
||||
|
||||
if (mock().hasData("RedisModule_Call_Return_Null"))
|
||||
return NULL;
|
||||
else
|
||||
return (RedisModuleCallReply *)1;
|
||||
}
|
||||
|
||||
void RedisModule_FreeCallReply(RedisModuleCallReply *reply)
|
||||
{
|
||||
(void)reply;
|
||||
mock().setData("RedisModule_FreeCallReply", mock().getData("RedisModule_FreeCallReply").getIntValue()+1);
|
||||
}
|
||||
|
||||
int RedisModule_CallReplyType(RedisModuleCallReply *reply)
|
||||
{
|
||||
|
||||
(void)reply;
|
||||
if (mock().hasData("RedisModule_CallReplyType_null"))
|
||||
{
|
||||
return REDISMODULE_REPLY_NULL;
|
||||
}
|
||||
|
||||
if (mock().hasData("RedisModule_CallReplyType_inter"))
|
||||
{
|
||||
return REDISMODULE_REPLY_INTEGER;
|
||||
}
|
||||
|
||||
if (mock().hasData("RedisModule_CallReplyType_str"))
|
||||
{
|
||||
return REDISMODULE_REPLY_STRING;
|
||||
}
|
||||
|
||||
if (mock().hasData("RedisModule_CallReplyType_err"))
|
||||
{
|
||||
return REDISMODULE_REPLY_ERROR;
|
||||
}
|
||||
|
||||
return REDISMODULE_REPLY_NULL;;
|
||||
|
||||
}
|
||||
|
||||
long long RedisModule_CallReplyInteger(RedisModuleCallReply *reply)
|
||||
{
|
||||
|
||||
(void)reply;
|
||||
return mock().getData("RedisModule_CallReplyInteger").getIntValue();
|
||||
}
|
||||
|
||||
const char *RedisModule_StringPtrLen(const RedisModuleString *str, size_t *len)
|
||||
{
|
||||
|
||||
(void)str;
|
||||
if (len) *len = 5;
|
||||
if (mock().hasData("RedisModule_String_same"))
|
||||
{
|
||||
return "11111";
|
||||
}
|
||||
|
||||
if (mock().hasData("RedisModule_String_nosame"))
|
||||
{
|
||||
return "22222";
|
||||
}
|
||||
|
||||
if (mock().hasData("RedisModule_String_count"))
|
||||
{
|
||||
return "COUNT";
|
||||
}
|
||||
|
||||
if (mock().hasData("RedisModule_String_count1"))
|
||||
{
|
||||
if (len) *len = 6;
|
||||
return "COUNT1";
|
||||
}
|
||||
|
||||
return "11111";
|
||||
}
|
||||
|
||||
int RedisModule_ReplyWithError(RedisModuleCtx *ctx, const char *err)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)err;
|
||||
mock().setData("RedisModule_ReplyWithError", 1);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
int RedisModule_ReplyWithString(RedisModuleCtx *ctx, RedisModuleString *str)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)str;
|
||||
mock().setData("RedisModule_ReplyWithString", mock().getData("RedisModule_ReplyWithString").getIntValue()+1);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
int RedisModule_ReplyWithNull(RedisModuleCtx *ctx)
|
||||
{
|
||||
|
||||
(void)ctx;
|
||||
mock().setData("RedisModule_ReplyWithNull", 1);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
int RedisModule_ReplyWithCallReply(RedisModuleCtx *ctx, RedisModuleCallReply *reply)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)reply;
|
||||
mock().setData("RedisModule_ReplyWithCallReply", 1);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
const char *RedisModule_CallReplyStringPtr(RedisModuleCallReply *reply, size_t *len)
|
||||
{
|
||||
(void)reply;
|
||||
|
||||
if (mock().hasData("RedisModule_String_same"))
|
||||
{
|
||||
if (len)
|
||||
*len = 5;
|
||||
return "11111";
|
||||
}
|
||||
|
||||
if (mock().hasData("RedisModule_String_nosame"))
|
||||
{
|
||||
if (len)
|
||||
*len = 6;
|
||||
return "333333";
|
||||
}
|
||||
|
||||
return "11111";
|
||||
}
|
||||
|
||||
RedisModuleString *RedisModule_CreateStringFromCallReply(RedisModuleCallReply *reply)
|
||||
{
|
||||
(void)reply;
|
||||
return (RedisModuleString *)1;
|
||||
}
|
||||
|
||||
|
||||
int RedisModule_KeyType(RedisModuleKey *kp)
|
||||
{
|
||||
|
||||
|
||||
(void)kp;
|
||||
if (mock().hasData("RedisModule_KeyType_empty"))
|
||||
{
|
||||
return REDISMODULE_KEYTYPE_EMPTY;
|
||||
}
|
||||
|
||||
if (mock().hasData("RedisModule_KeyType_str"))
|
||||
{
|
||||
return REDISMODULE_KEYTYPE_STRING;
|
||||
}
|
||||
|
||||
if (mock().hasData("RedisModule_KeyType_set"))
|
||||
{
|
||||
|
||||
return REDISMODULE_KEYTYPE_SET;
|
||||
}
|
||||
|
||||
return REDISMODULE_KEYTYPE_EMPTY;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void RedisModule_CloseKey(RedisModuleKey *kp)
|
||||
{
|
||||
(void)kp;
|
||||
mock().actualCall("RedisModule_CloseKey");
|
||||
}
|
||||
|
||||
/* This is included inline inside each Redis module. */
|
||||
int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)name;
|
||||
(void)ver;
|
||||
(void)apiver;
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
size_t RedisModule_CallReplyLength(RedisModuleCallReply *reply)
|
||||
{
|
||||
(void)reply;
|
||||
return mock().getData("RedisModule_CallReplyLength").getIntValue();
|
||||
}
|
||||
|
||||
|
||||
RedisModuleCallReply *RedisModule_CallReplyArrayElement(RedisModuleCallReply *reply, size_t idx)
|
||||
{
|
||||
(void)reply;
|
||||
(void)idx;
|
||||
return (RedisModuleCallReply *)1;
|
||||
}
|
||||
|
||||
int RedisModule_ReplyWithArray(RedisModuleCtx *ctx, long len)
|
||||
{
|
||||
(void)ctx;
|
||||
mock().setData("RedisModule_ReplyWithArray", (int)len);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
void RedisModule_FreeString(RedisModuleCtx *ctx, RedisModuleString *str)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)str;
|
||||
mock().setData("RedisModule_FreeString", mock().getData("RedisModule_FreeString").getIntValue()+1);
|
||||
return;
|
||||
}
|
||||
|
||||
RedisModuleBlockedClient *RedisModule_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)reply_callback;
|
||||
(void)timeout_callback;
|
||||
(void)free_privdata;
|
||||
(void)timeout_ms;
|
||||
RedisModuleBlockedClient *bc = (RedisModuleBlockedClient*)malloc(sizeof(RedisModuleBlockedClient));
|
||||
mock().setData("RedisModule_BlockClient", 1);
|
||||
return bc;
|
||||
}
|
||||
|
||||
int RedisModule_UnblockClient(RedisModuleBlockedClient *bc, void *privdata)
|
||||
{
|
||||
(void)privdata;
|
||||
free(bc);
|
||||
mock().setData("RedisModule_UnblockClient", mock().getData("RedisModule_UnblockClient").getIntValue()+1);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
int RedisModule_AbortBlock(RedisModuleBlockedClient *bc)
|
||||
{
|
||||
free(bc);
|
||||
mock().setData("RedisModule_AbortBlock", 1);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
RedisModuleString *RedisModule_CreateString(RedisModuleCtx *ctx, const char *ptr, size_t len)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)ptr;
|
||||
(void)len;
|
||||
RedisModuleString *rms = (RedisModuleString*)malloc(sizeof(RedisModuleString));
|
||||
mock().setData("RedisModule_CreateString", mock().getData("RedisModule_CreateString").getIntValue()+1);
|
||||
return rms;
|
||||
}
|
||||
|
||||
void RedisModule_FreeThreadSafeContext(RedisModuleCtx *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
mock().setData("RedisModule_FreeThreadSafeContext", 1);
|
||||
return;
|
||||
}
|
||||
|
||||
int RedisModule_StringToLongLong(const RedisModuleString *str, long long *ll)
|
||||
{
|
||||
(void)str;
|
||||
|
||||
int call_no = mock().getData("RedisModule_StringToLongLongCallCount").getIntValue();
|
||||
switch(call_no) {
|
||||
case 0:
|
||||
*ll = mock().getData("RedisModule_StringToLongLongCall_1").getIntValue();
|
||||
break;
|
||||
case 1:
|
||||
*ll = mock().getData("RedisModule_StringToLongLongCall_2").getIntValue();
|
||||
break;
|
||||
default:
|
||||
*ll = mock().getData("RedisModule_StringToLongLongCallDefault").getIntValue();
|
||||
}
|
||||
mock().setData("RedisModule_StringToLongLongCallCount", call_no + 1);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
void RedisModule_ThreadSafeContextLock(RedisModuleCtx *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
mock().setData("RedisModule_ThreadSafeContextLock", 1);
|
||||
return;
|
||||
}
|
||||
|
||||
void RedisModule_ThreadSafeContextUnlock(RedisModuleCtx *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
mock().setData("RedisModule_ThreadSafeContextUnlock", 1);
|
||||
return;
|
||||
}
|
||||
|
||||
void RedisModule_ReplySetArrayLength(RedisModuleCtx *ctx, long len)
|
||||
{
|
||||
(void)ctx;
|
||||
mock().setData("RedisModule_ReplySetArrayLength", (int)len);
|
||||
return;
|
||||
}
|
||||
|
||||
RedisModuleCtx *RedisModule_GetThreadSafeContext(RedisModuleBlockedClient *bc)
|
||||
{
|
||||
(void) bc;
|
||||
mock().setData("RedisModule_GetThreadSafeContext", 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RedisModuleString *RedisModule_CreateStringFromLongLong(RedisModuleCtx *ctx, long long ll)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)ll;
|
||||
RedisModuleString *rms = (RedisModuleString*)malloc(sizeof(RedisModuleString));
|
||||
mock().setData("RedisModule_CreateStringFromLongLong", mock().getData("RedisModule_CreateStringFromLongLong").getIntValue()+1);
|
||||
return rms;
|
||||
}
|
||||
|
||||
void RedisModule_AutoMemory(RedisModuleCtx *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
int old = mock().getData("RedisModule_AutoMemory").getIntValue();
|
||||
mock().setData("RedisModule_AutoMemory", old + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
void *RedisModule_Alloc(size_t bytes)
|
||||
{
|
||||
mock()
|
||||
.actualCall("RedisModule_Alloc");
|
||||
return malloc(bytes);
|
||||
}
|
||||
|
||||
void RedisModule_Free(void *ptr)
|
||||
{
|
||||
mock()
|
||||
.actualCall("RedisModule_Free");
|
||||
free(ptr);
|
||||
}
|
164
setup/dbaas/redismodule/tst/src/exstrings_ndel_test.cpp
Normal file
164
setup/dbaas/redismodule/tst/src/exstrings_ndel_test.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Nokia.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
* platform project (RICP).
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "exstringsStub.h"
|
||||
#include "redismodule.h"
|
||||
}
|
||||
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "CppUTestExt/MockSupport.h"
|
||||
|
||||
#include "ut_helpers.hpp"
|
||||
|
||||
void nDelReturnNKeysFromUnlink(int count)
|
||||
{
|
||||
mock()
|
||||
.expectOneCall("RedisModule_CallReplyInteger")
|
||||
.andReturnValue(count);
|
||||
|
||||
}
|
||||
|
||||
TEST_GROUP(exstrings_ndel)
|
||||
{
|
||||
void setup()
|
||||
{
|
||||
mock().enable();
|
||||
mock().ignoreOtherCalls();
|
||||
}
|
||||
|
||||
void teardown()
|
||||
{
|
||||
mock().clear();
|
||||
mock().disable();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TEST(exstrings_ndel, ndel_atomic_automemory_enabled)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
mock().expectOneCall("RedisModule_AutoMemory");
|
||||
int ret = NDel_Atomic_RedisCommand(&ctx, redisStrVec, 3);
|
||||
mock().checkExpectations();
|
||||
CHECK_EQUAL(ret, REDISMODULE_ERR);
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_ndel, ndel_atomic_command_parameter_parameter_number_incorrect)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
mock().expectOneCall("RedisModule_WrongArity");
|
||||
int ret = NDel_Atomic_RedisCommand(&ctx, redisStrVec, 3);
|
||||
mock().checkExpectations();
|
||||
CHECK_EQUAL(ret, REDISMODULE_ERR);
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_ndel, ndel_atomic_command_scan_0_keys_found)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
returnNKeysFromScanSome(0);
|
||||
mock().expectOneCall("RedisModule_ReplyWithLongLong")
|
||||
.withParameter("ll", 0);
|
||||
int ret = NDel_Atomic_RedisCommand(&ctx, redisStrVec, 2);
|
||||
mock().checkExpectations();
|
||||
CHECK_EQUAL(ret, REDISMODULE_OK);
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_ndel, ndel_atomic_command_scan_3_keys_found_3_keys_deleted)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "SCAN");
|
||||
returnNKeysFromScanSome(3);
|
||||
mock()
|
||||
.expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "UNLINK");
|
||||
nDelReturnNKeysFromUnlink(3);
|
||||
mock().expectOneCall("RedisModule_ReplyWithLongLong")
|
||||
.withParameter("ll", 3);
|
||||
int ret = NDel_Atomic_RedisCommand(&ctx, redisStrVec, 2);
|
||||
mock().checkExpectations();
|
||||
CHECK_EQUAL(ret, REDISMODULE_OK);
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_ndel, ndel_atomic_command_scan_3_keys_found_0_keys_deleted)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "SCAN");
|
||||
returnNKeysFromScanSome(3);
|
||||
mock()
|
||||
.expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "UNLINK");
|
||||
nDelReturnNKeysFromUnlink(0);
|
||||
mock().expectOneCall("RedisModule_ReplyWithLongLong")
|
||||
.withParameter("ll", 0);
|
||||
int ret = NDel_Atomic_RedisCommand(&ctx, redisStrVec, 2);
|
||||
mock().checkExpectations();
|
||||
CHECK_EQUAL(ret, REDISMODULE_OK);
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_ndel, ndel_atomic_command_scan_3_keys_found_1_keys_deleted)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "SCAN");
|
||||
returnNKeysFromScanSome(3);
|
||||
mock()
|
||||
.expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "UNLINK");
|
||||
nDelReturnNKeysFromUnlink(1);
|
||||
mock().expectOneCall("RedisModule_ReplyWithLongLong")
|
||||
.withParameter("ll", 1);
|
||||
int ret = NDel_Atomic_RedisCommand(&ctx, redisStrVec, 2);
|
||||
mock().checkExpectations();
|
||||
CHECK_EQUAL(ret, REDISMODULE_OK);
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
552
setup/dbaas/redismodule/tst/src/exstrings_nget_test.cpp
Normal file
552
setup/dbaas/redismodule/tst/src/exstrings_nget_test.cpp
Normal file
@@ -0,0 +1,552 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Nokia.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
* platform project (RICP).
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "exstringsStub.h"
|
||||
#include "redismodule.h"
|
||||
}
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "CppUTestExt/MockSupport.h"
|
||||
|
||||
#include "ut_helpers.hpp"
|
||||
|
||||
TEST_GROUP(exstrings_nget)
|
||||
{
|
||||
void setup()
|
||||
{
|
||||
mock().enable();
|
||||
mock().ignoreOtherCalls();
|
||||
}
|
||||
|
||||
void teardown()
|
||||
{
|
||||
mock().clear();
|
||||
mock().disable();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void threadDetachedSuccess()
|
||||
{
|
||||
mock().expectOneCall("pthread_detach")
|
||||
.andReturnValue(0);
|
||||
}
|
||||
|
||||
void nKeysFoundMget(long keys)
|
||||
{
|
||||
for (long i = 0 ; i < keys ; i++) {
|
||||
mock().expectOneCall("RedisModule_CreateStringFromCallReply")
|
||||
.andReturnValue(malloc(UT_DUMMY_BUFFER_SIZE));
|
||||
mock().expectNCalls(2, "RedisModule_ReplyWithString");
|
||||
}
|
||||
}
|
||||
|
||||
void nKeysNotFoundMget(long keys)
|
||||
{
|
||||
void* ptr = NULL;
|
||||
mock().expectNCalls(keys, "RedisModule_CreateStringFromCallReply")
|
||||
.andReturnValue(ptr);
|
||||
mock().expectNoCall("RedisModule_ReplyWithString");
|
||||
}
|
||||
|
||||
void expectNReplies(long count)
|
||||
{
|
||||
mock().expectOneCall("RedisModule_ReplySetArrayLength")
|
||||
.withParameter("len", 2*count);
|
||||
}
|
||||
|
||||
void threadSafeContextLockedAndUnlockedEqualTimes()
|
||||
{
|
||||
int locked = mock().getData("TimesThreadSafeContextWasLocked").getIntValue();
|
||||
int unlocked = mock().getData("TimesThreadSafeContextWasUnlocked").getIntValue();
|
||||
CHECK_EQUAL(locked, unlocked);
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_atomic_automemory_enabled)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
long keys_found_with_scan = 0;
|
||||
|
||||
mock().expectOneCall("RedisModule_AutoMemory");
|
||||
mock().expectOneCall("RedisModule_CallReplyLength")
|
||||
.andReturnValue((int)keys_found_with_scan);
|
||||
int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
|
||||
mock().checkExpectations();
|
||||
CHECK_EQUAL(ret, REDISMODULE_OK);
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_atomic_command_parameter_number_incorrect)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().expectOneCall("RedisModule_WrongArity");
|
||||
int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 3);
|
||||
CHECK_EQUAL(ret, REDISMODULE_ERR);
|
||||
mock().checkExpectations();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_atomic_command_3rd_parameter_was_not_equal_to_COUNT)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(4);
|
||||
const char * not_count_literal = "NOT_COUNT";
|
||||
size_t not_count_len = strlen(not_count_literal);
|
||||
|
||||
mock().expectOneCall("RedisModule_StringPtrLen")
|
||||
.withOutputParameterReturning("len", ¬_count_len, sizeof(size_t))
|
||||
.andReturnValue((void*)not_count_literal);
|
||||
mock().expectOneCall("RedisModule_ReplyWithError");
|
||||
int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 4);
|
||||
CHECK_EQUAL(ret, REDISMODULE_ERR);
|
||||
mock().checkExpectations();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_atomic_command_4th_parameter_was_not_integer)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(4);
|
||||
const char * count_literal = "COUNT";
|
||||
size_t count_len = strlen(count_literal);
|
||||
size_t count_number = 123;
|
||||
|
||||
mock().expectOneCall("RedisModule_StringPtrLen")
|
||||
.withOutputParameterReturning("len", &count_len, sizeof(size_t))
|
||||
.andReturnValue((void*)count_literal);
|
||||
mock().expectOneCall("RedisModule_StringToLongLong")
|
||||
.withOutputParameterReturning("ll", &count_number, sizeof(size_t))
|
||||
.andReturnValue(REDISMODULE_ERR);
|
||||
mock().expectOneCall("RedisModule_ReplyWithError");
|
||||
int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 4);
|
||||
CHECK_EQUAL(ret, REDISMODULE_ERR);
|
||||
mock().checkExpectations();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_atomic_command_4th_parameter_was_negative)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(4);
|
||||
const char * count_literal = "COUNT";
|
||||
size_t count_len = strlen(count_literal);
|
||||
size_t count_number = -123;
|
||||
|
||||
mock().expectOneCall("RedisModule_StringPtrLen")
|
||||
.withOutputParameterReturning("len", &count_len, sizeof(size_t))
|
||||
.andReturnValue((void*)count_literal);
|
||||
mock().expectOneCall("RedisModule_StringToLongLong")
|
||||
.withOutputParameterReturning("ll", &count_number, sizeof(size_t))
|
||||
.andReturnValue(REDISMODULE_OK);
|
||||
mock().expectOneCall("RedisModule_ReplyWithError");
|
||||
int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 4);
|
||||
CHECK_EQUAL(ret, REDISMODULE_ERR);
|
||||
mock().checkExpectations();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_atomic_command_scan_returned_zero_keys)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().expectOneCall("RedisModule_ReplyWithArray")
|
||||
.withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "SCAN");
|
||||
returnNKeysFromScanSome(0);
|
||||
expectNReplies(0);
|
||||
mock().expectNoCall("RedisModule_Call");
|
||||
|
||||
int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
|
||||
CHECK_EQUAL(ret, REDISMODULE_OK);
|
||||
mock().checkExpectations();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_0_keys_mget)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
mock().expectOneCall("RedisModule_ReplyWithArray")
|
||||
.withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
|
||||
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "SCAN");
|
||||
returnNKeysFromScanSome(3);
|
||||
mock().expectOneCall("RedisModule_FreeCallReply");
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "MGET");
|
||||
nKeysNotFoundMget(3);
|
||||
mock().expectOneCall("RedisModule_FreeCallReply");
|
||||
expectNReplies(0);
|
||||
int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
|
||||
CHECK_EQUAL(ret, REDISMODULE_OK);
|
||||
mock().checkExpectations();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_3_keys_mget)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
mock().expectOneCall("RedisModule_ReplyWithArray")
|
||||
.withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "SCAN");
|
||||
returnNKeysFromScanSome(3);
|
||||
mock().expectOneCall("RedisModule_FreeCallReply");
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "MGET");
|
||||
nKeysFoundMget(3);
|
||||
mock().expectOneCall("RedisModule_FreeCallReply");
|
||||
expectNReplies(3);
|
||||
int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
|
||||
CHECK_EQUAL(ret, REDISMODULE_OK);
|
||||
mock().checkExpectations();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_2_keys_mget)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
mock().expectOneCall("RedisModule_ReplyWithArray")
|
||||
.withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "SCAN");
|
||||
returnNKeysFromScanSome(3);
|
||||
mock().expectOneCall("RedisModule_FreeCallReply");
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "MGET");
|
||||
nKeysFoundMget(2);
|
||||
nKeysNotFoundMget(1);
|
||||
mock().expectOneCall("RedisModule_FreeCallReply");
|
||||
expectNReplies(2);
|
||||
int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
|
||||
CHECK_EQUAL(ret, REDISMODULE_OK);
|
||||
mock().checkExpectations();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_noatomic_automemory_enabled)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().setData("pthread_create_free_block_client_args", 1);
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
mock().expectOneCall("RedisModule_AutoMemory");
|
||||
|
||||
int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 2);
|
||||
CHECK_EQUAL(ret, REDISMODULE_OK);
|
||||
mock().checkExpectations();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_noatomic_thread_create_success)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().setData("pthread_create_free_block_client_args", 1);
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
mock().expectOneCall("RedisModule_BlockClient");
|
||||
mock().expectOneCall("pthread_create");
|
||||
mock().expectNoCall("RedisModule_AbortBlock");
|
||||
|
||||
int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 2);
|
||||
CHECK_EQUAL(ret, REDISMODULE_OK);
|
||||
mock().checkExpectations();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_noatomic_thread_create_fail)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
mock().expectOneCall("RedisModule_BlockClient");
|
||||
mock().expectOneCall("pthread_create")
|
||||
.andReturnValue(1);
|
||||
mock().expectOneCall("RedisModule_AbortBlock");
|
||||
|
||||
int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 2);
|
||||
CHECK_EQUAL(ret, REDISMODULE_OK);
|
||||
mock().checkExpectations();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_noatomic_parameter_number_incorrect)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(4);
|
||||
|
||||
mock().expectOneCall("RedisModule_WrongArity");
|
||||
mock().expectNoCall("RedisModule_BlockClient");
|
||||
|
||||
int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 3);
|
||||
|
||||
CHECK_EQUAL(ret, REDISMODULE_ERR);
|
||||
mock().checkExpectations();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_noatomic_threadmain_3rd_parameter_was_not_equal_to_COUNT)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(4);
|
||||
const char * not_count_literal = "NOT_COUNT";
|
||||
size_t not_count_len = strlen(not_count_literal);
|
||||
|
||||
mock().expectOneCall("RedisModule_StringPtrLen")
|
||||
.withOutputParameterReturning("len", ¬_count_len, sizeof(size_t))
|
||||
.andReturnValue((void*)not_count_literal);
|
||||
mock().expectOneCall("RedisModule_ReplyWithError");
|
||||
mock().expectNoCall("RedisModule_BlockClient");
|
||||
|
||||
int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 4);
|
||||
|
||||
CHECK_EQUAL(ret, REDISMODULE_ERR);
|
||||
|
||||
mock().checkExpectations();
|
||||
threadSafeContextLockedAndUnlockedEqualTimes();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_noatomic_4th_parameter_was_not_integer)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
const char * count_literal = "COUNT";
|
||||
size_t count_len = strlen(count_literal);
|
||||
size_t count_number = -123;
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(4);
|
||||
|
||||
mock().expectOneCall("RedisModule_StringPtrLen")
|
||||
.withOutputParameterReturning("len", &count_len, sizeof(size_t))
|
||||
.andReturnValue((void*)count_literal);
|
||||
mock().expectOneCall("RedisModule_StringToLongLong")
|
||||
.withOutputParameterReturning("ll", &count_number, sizeof(size_t))
|
||||
.andReturnValue(REDISMODULE_OK);
|
||||
mock().expectOneCall("RedisModule_ReplyWithError");
|
||||
|
||||
int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 4);
|
||||
|
||||
CHECK_EQUAL(ret, REDISMODULE_ERR);
|
||||
mock().checkExpectations();
|
||||
threadSafeContextLockedAndUnlockedEqualTimes();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
typedef struct RedisModuleBlockedClientArgs {
|
||||
RedisModuleBlockedClient *bc;
|
||||
RedisModuleString **argv;
|
||||
int argc;
|
||||
} RedisModuleBlockedClientArgs;
|
||||
|
||||
TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_3_keys_mget)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleBlockedClientArgs *bca =
|
||||
(RedisModuleBlockedClientArgs*)RedisModule_Alloc(sizeof(RedisModuleBlockedClientArgs));
|
||||
RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
bca->bc = bc;
|
||||
bca->argv = redisStrVec;
|
||||
bca->argc = 2;
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
threadDetachedSuccess();
|
||||
mock().expectOneCall("RedisModule_ReplyWithArray")
|
||||
.withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "SCAN");
|
||||
returnNKeysFromScanSome(3);
|
||||
mock().expectOneCall("RedisModule_FreeCallReply");
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "MGET");
|
||||
nKeysFoundMget(3);
|
||||
mock().expectOneCall("RedisModule_FreeCallReply");
|
||||
expectNReplies(3);
|
||||
mock().expectOneCall("RedisModule_FreeThreadSafeContext");
|
||||
mock().expectOneCall("RedisModule_UnblockClient");
|
||||
|
||||
NGet_NoAtomic_ThreadMain((void*)bca);
|
||||
|
||||
mock().checkExpectations();
|
||||
threadSafeContextLockedAndUnlockedEqualTimes();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_0_keys_mget)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
|
||||
RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
bca->bc = bc;
|
||||
bca->argv = redisStrVec;
|
||||
bca->argc = 2;
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
threadDetachedSuccess();
|
||||
mock().expectOneCall("RedisModule_ReplyWithArray")
|
||||
.withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "SCAN");
|
||||
returnNKeysFromScanSome(3);
|
||||
mock().expectOneCall("RedisModule_FreeCallReply");
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "MGET");
|
||||
nKeysNotFoundMget(3);
|
||||
mock().expectOneCall("RedisModule_FreeCallReply");
|
||||
expectNReplies(0);
|
||||
mock().expectOneCall("RedisModule_FreeThreadSafeContext");
|
||||
mock().expectOneCall("RedisModule_UnblockClient");
|
||||
|
||||
NGet_NoAtomic_ThreadMain((void*)bca);
|
||||
|
||||
mock().checkExpectations();
|
||||
threadSafeContextLockedAndUnlockedEqualTimes();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_2_keys_mget)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
|
||||
RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
bca->bc = bc;
|
||||
bca->argv = redisStrVec;
|
||||
bca->argc = 2;
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
threadDetachedSuccess();
|
||||
mock().expectOneCall("RedisModule_ReplyWithArray")
|
||||
.withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "SCAN");
|
||||
returnNKeysFromScanSome(3);
|
||||
mock().expectOneCall("RedisModule_FreeCallReply");
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "MGET");
|
||||
nKeysNotFoundMget(1);
|
||||
nKeysFoundMget(2);
|
||||
mock().expectOneCall("RedisModule_FreeCallReply");
|
||||
expectNReplies(2);
|
||||
mock().expectOneCall("RedisModule_FreeThreadSafeContext");
|
||||
mock().expectOneCall("RedisModule_UnblockClient");
|
||||
|
||||
NGet_NoAtomic_ThreadMain((void*)bca);
|
||||
|
||||
mock().checkExpectations();
|
||||
threadSafeContextLockedAndUnlockedEqualTimes();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_noatomic_threadmain_scan_returned_zero_keys)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
|
||||
RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
bca->bc = bc;
|
||||
bca->argv = redisStrVec;
|
||||
bca->argc = 2;
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
threadDetachedSuccess();
|
||||
mock().expectOneCall("RedisModule_ReplyWithArray")
|
||||
.withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
|
||||
mock().expectOneCall("RedisModule_Call")
|
||||
.withParameter("cmdname", "SCAN");
|
||||
returnNKeysFromScanSome(0);
|
||||
mock().expectOneCall("RedisModule_FreeCallReply");
|
||||
mock().expectNoCall("RedisModule_Call");
|
||||
mock().expectOneCall("RedisModule_FreeThreadSafeContext");
|
||||
mock().expectOneCall("RedisModule_UnblockClient");
|
||||
|
||||
NGet_NoAtomic_ThreadMain((void*)bca);
|
||||
|
||||
mock().checkExpectations();
|
||||
threadSafeContextLockedAndUnlockedEqualTimes();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
||||
|
||||
TEST(exstrings_nget, nget_noatomic_threadmain_thread_detached)
|
||||
{
|
||||
RedisModuleCtx ctx;
|
||||
RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
|
||||
RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
|
||||
RedisModuleString ** redisStrVec = createRedisStrVec(2);
|
||||
|
||||
bca->bc = bc;
|
||||
bca->argv = redisStrVec;
|
||||
bca->argc = 2;
|
||||
|
||||
mock().ignoreOtherCalls();
|
||||
threadDetachedSuccess();
|
||||
|
||||
NGet_NoAtomic_ThreadMain((void*)bca);
|
||||
|
||||
mock().checkExpectations();
|
||||
|
||||
delete []redisStrVec;
|
||||
}
|
1691
setup/dbaas/redismodule/tst/src/exstrings_test.cpp
Executable file
1691
setup/dbaas/redismodule/tst/src/exstrings_test.cpp
Executable file
File diff suppressed because it is too large
Load Diff
32
setup/dbaas/redismodule/tst/src/main.cpp
Executable file
32
setup/dbaas/redismodule/tst/src/main.cpp
Executable file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Nokia.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
* platform project (RICP).
|
||||
*/
|
||||
|
||||
#include "CppUTest/CommandLineTestRunner.h"
|
||||
|
||||
extern "C" {
|
||||
#include <stdio.h>
|
||||
}
|
||||
|
||||
int main(int ac, char** av)
|
||||
{
|
||||
MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
|
||||
return CommandLineTestRunner::RunAllTests(ac, av);
|
||||
}
|
48
setup/dbaas/redismodule/tst/src/ut_helpers.cpp
Normal file
48
setup/dbaas/redismodule/tst/src/ut_helpers.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Nokia.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
* platform project (RICP).
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "redismodule.h"
|
||||
#include "ut_helpers.hpp"
|
||||
|
||||
#include <CppUTest/TestHarness.h>
|
||||
#include <CppUTestExt/MockSupport.h>
|
||||
|
||||
RedisModuleString **createRedisStrVec(size_t size)
|
||||
{
|
||||
RedisModuleString ** redisStrVec = new RedisModuleString*[size];
|
||||
for (size_t i = 0 ; i < size ; i++) {
|
||||
redisStrVec[i] = (RedisModuleString *)UT_DUMMY_PTR_ADDRESS;
|
||||
}
|
||||
return redisStrVec;
|
||||
}
|
||||
|
||||
void returnNKeysFromScanSome(long keys)
|
||||
{
|
||||
mock().expectOneCall("RedisModule_CallReplyLength")
|
||||
.andReturnValue((int)keys);
|
||||
for (long i = 0 ; i < keys ; i++) {
|
||||
mock().expectOneCall("RedisModule_CreateStringFromCallReply")
|
||||
.andReturnValue(malloc(UT_DUMMY_BUFFER_SIZE));
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,10 @@
|
||||
---
|
||||
distribution_type: container
|
||||
container_release_tag: 0.1.0
|
||||
container_pull_registry: nexus3.o-ran-sc.org:10004
|
||||
container_push_registry: nexus3.o-ran-sc.org:10002
|
||||
project: ric-plt/dbaas
|
||||
ref: a3454f896b5dc62ee0672febcb228a1b7c20e63e
|
||||
containers:
|
||||
- name: ric-plt-dbaas
|
||||
version: 0.1.0
|
10
setup/dbaas/releases/container-release-ric-plt-dbaas.yaml
Normal file
10
setup/dbaas/releases/container-release-ric-plt-dbaas.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
distribution_type: container
|
||||
container_release_tag: 0.4.0
|
||||
container_pull_registry: nexus3.o-ran-sc.org:10004
|
||||
container_push_registry: nexus3.o-ran-sc.org:10002
|
||||
project: ric-plt/dbaas
|
||||
ref: c8a0448d6b8f67f0c0bae546eeb8c0aae9914837
|
||||
containers:
|
||||
- name: ric-plt-dbaas
|
||||
version: 0.4.0
|
139
setup/dbaas/testapplication/go/sdl/sdl.go
Normal file
139
setup/dbaas/testapplication/go/sdl/sdl.go
Normal file
@@ -0,0 +1,139 @@
|
||||
// Copyright (c) 2019 AT&T Intellectual Property.
|
||||
// Copyright (c) 2019 Nokia.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//
|
||||
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
// platform project (RICP).
|
||||
//
|
||||
|
||||
package sdl
|
||||
|
||||
import (
|
||||
"github.com/go-redis/redis"
|
||||
"os"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type SdlInstance struct {
|
||||
nameSpace string
|
||||
nsPrefix string
|
||||
client *redis.Client
|
||||
}
|
||||
|
||||
func Create(nameSpace string) *SdlInstance {
|
||||
hostname := os.Getenv("DBAAS_SERVICE_HOST")
|
||||
if hostname == "" {
|
||||
hostname = "localhost"
|
||||
}
|
||||
port := os.Getenv("DBAAS_SERVICE_PORT")
|
||||
if port == "" {
|
||||
port = "6379"
|
||||
}
|
||||
redisAddress := hostname + ":" + port
|
||||
client := redis.NewClient(&redis.Options{
|
||||
Addr: redisAddress,
|
||||
Password: "", // no password set
|
||||
DB: 0, // use default DB
|
||||
})
|
||||
|
||||
s := SdlInstance{
|
||||
nameSpace: nameSpace,
|
||||
nsPrefix: "{" + nameSpace + "},",
|
||||
client: client,
|
||||
}
|
||||
|
||||
return &s
|
||||
}
|
||||
|
||||
func (s *SdlInstance) setNamespaceToKeys(pairs ...interface{}) []interface{} {
|
||||
var retVal []interface{}
|
||||
for i, v := range pairs {
|
||||
if i%2 == 0 {
|
||||
reflectType := reflect.TypeOf(v)
|
||||
switch reflectType.Kind() {
|
||||
case reflect.Slice:
|
||||
x := reflect.ValueOf(v)
|
||||
for i2 := 0; i2 < x.Len(); i2++ {
|
||||
if i2%2 == 0 {
|
||||
retVal = append(retVal, s.nsPrefix+x.Index(i2).Interface().(string))
|
||||
} else {
|
||||
retVal = append(retVal, x.Index(i2).Interface())
|
||||
}
|
||||
}
|
||||
case reflect.Array:
|
||||
x := reflect.ValueOf(v)
|
||||
for i2 := 0; i2 < x.Len(); i2++ {
|
||||
if i2%2 == 0 {
|
||||
retVal = append(retVal, s.nsPrefix+x.Index(i2).Interface().(string))
|
||||
} else {
|
||||
retVal = append(retVal, x.Index(i2).Interface())
|
||||
}
|
||||
}
|
||||
default:
|
||||
retVal = append(retVal, s.nsPrefix+v.(string))
|
||||
}
|
||||
} else {
|
||||
retVal = append(retVal, v)
|
||||
}
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (s *SdlInstance) Set(pairs ...interface{}) error {
|
||||
keyAndData := s.setNamespaceToKeys(pairs...)
|
||||
err := s.client.MSet(keyAndData...).Err()
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *SdlInstance) Get(keys []string) (map[string]interface{}, error) {
|
||||
var keysWithNs []string
|
||||
for _, v := range keys {
|
||||
keysWithNs = append(keysWithNs, s.nsPrefix+v)
|
||||
}
|
||||
val, err := s.client.MGet(keysWithNs...).Result()
|
||||
m := make(map[string]interface{})
|
||||
if err != nil {
|
||||
return m, err
|
||||
}
|
||||
for i, v := range val {
|
||||
m[keys[i]] = v
|
||||
}
|
||||
return m, err
|
||||
}
|
||||
|
||||
func (s *SdlInstance) SetIf(key string, oldData, newData interface{}) {
|
||||
panic("SetIf not implemented\n")
|
||||
}
|
||||
|
||||
func (s *SdlInstance) SetIfiNotExists(key string, data interface{}) {
|
||||
panic("SetIfiNotExists not implemented\n")
|
||||
}
|
||||
|
||||
func (s *SdlInstance) Remove(keys ...string) {
|
||||
panic("Remove not implemented\n")
|
||||
}
|
||||
|
||||
func (s *SdlInstance) RemoveIf(key string, data interface{}) {
|
||||
panic("RemoveIf not implemented\n")
|
||||
}
|
||||
|
||||
func (s *SdlInstance) GetAll() []string {
|
||||
panic("GetAll not implemented\n")
|
||||
}
|
||||
|
||||
func (s *SdlInstance) RemoveAll() {
|
||||
panic("RemoveAll not implemented\n")
|
||||
}
|
||||
|
104
setup/dbaas/testapplication/go/testapp.go
Normal file
104
setup/dbaas/testapplication/go/testapp.go
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) 2019 AT&T Intellectual Property.
|
||||
// Copyright (c) 2019 Nokia.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//
|
||||
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
// platform project (RICP).
|
||||
//
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"./sdl"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sdl1 := sdl.Create("test1")
|
||||
|
||||
var err error
|
||||
|
||||
err = sdl1.Set("key1", "data1", "key2", "data2")
|
||||
if err != nil {
|
||||
fmt.Printf("unable to write to DB\n")
|
||||
}
|
||||
|
||||
err = sdl1.Set("num1", 1, "num2", 2)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to write to DB\n")
|
||||
}
|
||||
|
||||
d := make([]byte, 3)
|
||||
d[0] = 1
|
||||
d[1] = 2
|
||||
d[2] = 3
|
||||
err = sdl1.Set("arr1", d)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to write to DB\n")
|
||||
}
|
||||
|
||||
p := []string{"pair1", "data1", "pair2", "data2"}
|
||||
err = sdl1.Set(p)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to write to DB\n")
|
||||
}
|
||||
|
||||
a := [4]string{"array1", "adata1", "array2", "adata2"}
|
||||
err = sdl1.Set(a)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to write to DB\n")
|
||||
}
|
||||
|
||||
mix1 := []interface{}{"mix1", "data1", "mix2", 2}
|
||||
err = sdl1.Set(mix1)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to write to DB\n")
|
||||
}
|
||||
|
||||
mix2 := [4]interface{}{"mix3", "data3", "mix4", 4}
|
||||
err = sdl1.Set(mix2)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to write to DB\n")
|
||||
}
|
||||
|
||||
retDataMap, err := sdl1.Get([]string{"key1", "key3", "key2"})
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to read from DB\n")
|
||||
} else {
|
||||
for i, v := range retDataMap {
|
||||
fmt.Printf("%s:%s\n", i, v)
|
||||
}
|
||||
}
|
||||
|
||||
retDataMap2, err := sdl1.Get([]string{"num1", "num2"})
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to read from DB\n")
|
||||
} else {
|
||||
for i, v := range retDataMap2 {
|
||||
fmt.Printf("%s:%s\n", i, v)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("-------------")
|
||||
allKeys := []string{"key1", "key2", "num1", "num2", "pair1", "pair2", "array1", "array2", "mix1", "mix2", "mix3", "mix4", "arr1"}
|
||||
retDataMap3, err := sdl1.Get(allKeys)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to read from DB\n")
|
||||
} else {
|
||||
for i3, v3 := range retDataMap3 {
|
||||
fmt.Printf("%s:%s\n", i3, v3)
|
||||
}
|
||||
}
|
||||
}
|
30
setup/dbaas/tox.ini
Normal file
30
setup/dbaas/tox.ini
Normal file
@@ -0,0 +1,30 @@
|
||||
# documentation only
|
||||
[tox]
|
||||
minversion = 2.0
|
||||
envlist =
|
||||
docs,
|
||||
docs-linkcheck,
|
||||
skipsdist = true
|
||||
|
||||
[testenv:docs]
|
||||
basepython = python3
|
||||
deps =
|
||||
sphinx
|
||||
sphinx-rtd-theme
|
||||
sphinxcontrib-httpdomain
|
||||
recommonmark
|
||||
lfdocs-conf
|
||||
|
||||
commands =
|
||||
sphinx-build -W -b html -n -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/html
|
||||
echo "Generated docs available in {toxinidir}/docs/_build/html"
|
||||
whitelist_externals = echo
|
||||
|
||||
[testenv:docs-linkcheck]
|
||||
basepython = python3
|
||||
deps = sphinx
|
||||
sphinx-rtd-theme
|
||||
sphinxcontrib-httpdomain
|
||||
recommonmark
|
||||
lfdocs-conf
|
||||
commands = sphinx-build -W -b linkcheck -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/linkcheck
|
Reference in New Issue
Block a user