├── .editorconfig ├── .github └── workflows │ ├── Http-Gateway-Release.yml │ ├── Http-Gateway-nightly.yml │ └── auto-cherry-pick.yml ├── .gitignore ├── Dockerfile ├── Makefile ├── README.md ├── ccore ├── go.mod ├── go.sum └── nebula │ ├── alias.go │ ├── client.go │ ├── client_graph.go │ ├── client_meta.go │ ├── client_storage_admin.go │ ├── driver.go │ ├── error.go │ ├── errors │ ├── error_code.go │ └── errors.go │ ├── examples │ └── main.go │ ├── factory.go │ ├── gateway │ ├── dao │ │ └── dao.go │ ├── examples │ │ └── main.go │ └── pool │ │ └── pool.go │ ├── internal │ ├── driver │ │ ├── v2_5 │ │ │ ├── driver.go │ │ │ ├── error_code.go │ │ │ ├── graph.go │ │ │ ├── meta.go │ │ │ ├── storage_admin.go │ │ │ └── wrapper.go │ │ ├── v2_6 │ │ │ ├── driver.go │ │ │ ├── error_code.go │ │ │ ├── graph.go │ │ │ ├── meta.go │ │ │ ├── storage_admin.go │ │ │ └── wrapper.go │ │ └── v3_0 │ │ │ ├── driver.go │ │ │ ├── error_code.go │ │ │ ├── graph.go │ │ │ ├── meta.go │ │ │ ├── storage_admin.go │ │ │ └── wrapper.go │ └── thrift │ │ ├── v2_5 │ │ ├── constants.go │ │ ├── graph │ │ │ ├── constants.go │ │ │ ├── graphservice.go │ │ │ └── ttypes.go │ │ ├── meta │ │ │ ├── constants.go │ │ │ ├── metaservice.go │ │ │ └── ttypes.go │ │ ├── storage │ │ │ ├── constants.go │ │ │ ├── generalstorageservice.go │ │ │ ├── graphstorageservice.go │ │ │ ├── storageadminservice.go │ │ │ └── ttypes.go │ │ └── ttypes.go │ │ ├── v2_6 │ │ ├── constants.go │ │ ├── graph │ │ │ ├── constants.go │ │ │ ├── graphservice.go │ │ │ └── ttypes.go │ │ ├── meta │ │ │ ├── constants.go │ │ │ ├── metaservice.go │ │ │ └── ttypes.go │ │ ├── storage │ │ │ ├── constants.go │ │ │ ├── generalstorageservice.go │ │ │ ├── graphstorageservice.go │ │ │ ├── storageadminservice.go │ │ │ └── ttypes.go │ │ └── ttypes.go │ │ └── v3_0 │ │ ├── constants.go │ │ ├── graph │ │ ├── constants.go │ │ ├── graph_service-remote │ │ │ └── graph_service-remote.go │ │ ├── graphservice.go │ │ └── ttypes.go │ │ ├── meta │ │ ├── constants.go │ │ ├── meta_service-remote │ │ │ └── meta_service-remote.go │ │ ├── metaservice.go │ │ └── ttypes.go │ │ ├── storage │ │ ├── constants.go │ │ ├── graph_storage_service-remote │ │ │ └── graph_storage_service-remote.go │ │ ├── graphstorageservice.go │ │ ├── storage_admin_service-remote │ │ │ └── storage_admin_service-remote.go │ │ ├── storageadminservice.go │ │ └── ttypes.go │ │ └── ttypes.go │ ├── logger.go │ ├── options.go │ ├── types │ ├── builder.go │ ├── driver.go │ ├── types.go │ └── version.go │ └── wrapper │ ├── result_set.go │ ├── value_wrapper.go │ └── wrapper.go ├── common ├── runtime.go └── tools.go ├── conf └── app.conf ├── controllers ├── db.go ├── db_test.go ├── task.go └── task_test.go ├── go.mod ├── go.sum ├── main.go ├── routers └── router.go └── service ├── importer ├── importer.go └── taskmgr.go └── logger └── adapter.go /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | insert_final_newline = true 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | indent_style = space 8 | indent_size = 2 9 | 10 | [{Makefile,go.mod,go.sum,*.go}] 11 | indent_style = tab 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /.github/workflows/Http-Gateway-Release.yml: -------------------------------------------------------------------------------- 1 | name: Http-Gateway-Release 2 | on: 3 | release: 4 | types: 5 | - published 6 | jobs: 7 | release-image: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - 11 | name: Checkout Github Action 12 | uses: actions/checkout@master 13 | 14 | - 15 | name: Set up QEMU 16 | uses: docker/setup-qemu-action@v1 17 | - 18 | name: Set up Docker Buildx 19 | uses: docker/setup-buildx-action@v1 20 | - 21 | name: Login to DockerHub 22 | uses: docker/login-action@v1 23 | with: 24 | username: ${{ secrets.DOCKER_USERNAME }} 25 | password: ${{ secrets.DOCKER_PASSWORD }} 26 | - 27 | name: Build and push 28 | uses: docker/build-push-action@v2 29 | with: 30 | context: . 31 | file: ./Dockerfile 32 | push: true 33 | tags: vesoft/nebula-http-gateway:3.2.0 -------------------------------------------------------------------------------- /.github/workflows/Http-Gateway-nightly.yml: -------------------------------------------------------------------------------- 1 | name: Http-Gateway-nightly 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | release-image: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - 11 | name: Checkout Github Action 12 | uses: actions/checkout@master 13 | 14 | - 15 | name: Set up QEMU 16 | uses: docker/setup-qemu-action@v1 17 | - 18 | name: Set up Docker Buildx 19 | uses: docker/setup-buildx-action@v1 20 | - 21 | name: Login to DockerHub 22 | uses: docker/login-action@v1 23 | with: 24 | username: ${{ secrets.DOCKER_USERNAME }} 25 | password: ${{ secrets.DOCKER_PASSWORD }} 26 | - 27 | name: Build and push 28 | uses: docker/build-push-action@v2 29 | with: 30 | context: . 31 | file: ./Dockerfile 32 | push: true 33 | tags: vesoft/nebula-http-gateway:nightly -------------------------------------------------------------------------------- /.github/workflows/auto-cherry-pick.yml: -------------------------------------------------------------------------------- 1 | name: Auto Cherry Pick 2 | on: workflow_dispatch 3 | 4 | defaults: 5 | run: 6 | shell: bash 7 | 8 | jobs: 9 | auto-cherry-pick: 10 | runs-on: [self-hosted, nebula-fast] 11 | container: 12 | image: reg.vesoft-inc.com/dashboard/dashboard-dev:centos7 13 | credentials: 14 | username: ${{ secrets.HARBOR_USERNAME }} 15 | password: ${{ secrets.HARBOR_PASSWORD }} 16 | steps: 17 | - name: keep workspace empty 18 | run: | 19 | rm -rf * 20 | - name: git config set 21 | env: 22 | CLOUD_GH_PAT: ${{ secrets.GITHUB_TOKEN }} 23 | run: | 24 | git config --global url."https://${GITHUB_TOKEN}:x-oauth-basic@github.com/".insteadOf "https://github.com/" 25 | export GOPRIVATE="github.com/vesoft-inc" 26 | - name: auto cherry pick 27 | uses: xigongdaEricyang/cherry-pick-robot@with-python 28 | with: 29 | pr_label: ^v[0-9]*\.[0-9]*(.[0-9])?-cherry-pick$ 30 | repo_token: ${{ secrets.GITHUB_TOKEN }} 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | nebula-httpd 11 | 12 | # Output of the go coverage tool, specifically when used with LiteIDE 13 | *.out 14 | .idea 15 | .vscode/ 16 | vendor/ 17 | # Dependency directories (remove the comment below to include it) 18 | tmp/ 19 | 20 | err/ 21 | logs/ 22 | uploads/ 23 | *.db 24 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.13.1 as builder 2 | # Set the working directory to /app 3 | WORKDIR /nebula-http-gateway 4 | # Copy the current directory contents into the container at /app 5 | COPY . /nebula-http-gateway 6 | # Make port available to the world outside this container 7 | ENV GOPROXY https://goproxy.cn 8 | RUN go build 9 | 10 | FROM golang:1.13.1 11 | 12 | WORKDIR /root 13 | COPY --from=builder ./nebula-http-gateway . 14 | COPY ./conf ./conf 15 | 16 | EXPOSE 8080 17 | 18 | ENTRYPOINT ["./nebula-http-gateway"] 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build clean fmt test 2 | 3 | default: build 4 | 5 | clean: 6 | @go mod tidy && rm -rf nebula-httpd 7 | 8 | fmt: 9 | @find . -type f -iname \*.go -exec go fmt {} \; 10 | 11 | build: clean fmt 12 | @go build -o nebula-httpd main.go 13 | 14 | test: build 15 | ./nebula-httpd 16 | go test -v ./... 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nebula-http-gateway 2 | 3 | Gateway to provide a http interface for the Nebula Graph service. 4 | 5 | ## Build 6 | 7 | ```bash 8 | $ cd /path/to/nebula-http-gateway 9 | $ make 10 | ``` 11 | 12 | ## Run 13 | 14 | ```bash 15 | $ ./nebula-httpd 16 | ``` 17 | 18 | ## Required 19 | 20 | - Go 1.13+ 21 | - [beego](https://beego.me/) 22 | 23 | ## Version 24 | | Nebula Graph version | Http-gateway tag | 25 | |----------------------|---------------------------| 26 | | 1.x | v1.0 | 27 | | 2.0.x & 2.5.x | v2.0 | 28 | | 2.6.x | v2.1.x | 29 | | 3.0.x | 2.2.x | 30 | | 3.1.x | 3.1.x | 31 | | 3.2.x | 3.2.x | 32 | 33 | ## User Guide 34 | 35 | ### API Definition 36 | 37 | | Name | Path | Method | 38 | |------------|--------------------|--------| 39 | | connect | /api/db/connect | POST | 40 | | exec | /api/db/exec | POST | 41 | | disconnect | /api/db/disconnect | POST | 42 | 43 | #### Connect API #### 44 | 45 | The request json body 46 | 47 | ```json 48 | { 49 | "username": "user", 50 | "password": "password", 51 | "address": "192.168.8.26", 52 | "port": 9669 53 | } 54 | ``` 55 | 56 | The description of the parameters is as follows: 57 | 58 | | Field | Description | 59 | |----------|-----------------------------------------------------------------------------------------------------------------------------| 60 | | username | Sets the username of your Nebula Graph account. Before enabling authentication, you can use any characters as the username. | 61 | | password | Sets the password of your Nebula Graph account. Before enabling authentication, you can use any characters as the password. | 62 | | address | Sets the IP address of the graphd service. | 63 | | port | Sets the port number of the graphd service. The default port number is 9669. | 64 | 65 | ```bash 66 | $ curl -i -X POST \ 67 | -d '{"username":"user","password":"password","address":"192.168.8.26","port":9669}' \ 68 | http://127.0.0.1:8080/api/db/connect 69 | ``` 70 | 71 | response: 72 | 73 | ``` 74 | HTTP/1.1 200 OK 75 | Content-Length: 100 76 | Content-Type: application/json; charset=utf-8 77 | Server: beegoServer:1.12.3 78 | Set-Cookie: common-nsid=bec2e665ba62a13554b617d70de8b9b9; Path=/; HttpOnly 79 | Set-Cookie: Secure=true; Path=/ 80 | Set-Cookie: SameSite=None; Path=/ 81 | Date: Fri, 02 Apr 2021 08:49:18 GMT 82 | 83 | { 84 | "code": 0, 85 | "data": "5e18fa40-5343-422f-84e3-e7f9cad6b735", 86 | "message": "Login successfully" 87 | } 88 | ``` 89 | 90 | Notice: 91 | 92 | The response data nsid `5e18fa40-5343-422f-84e3-e7f9cad6b735` is encoded by HMAC-SH256 encryption algorithm, so it's not the same as what you get from a cookie. 93 | If you connect to the graphd service successfully, remember to save the *NSID* locally, which is important for the *exec* api to execute nGQL. 94 | If you restart the gateway server, all authenticated session will be lost, please be aware of this. 95 | 96 | #### Exec API #### 97 | 98 | The requested json body 99 | 100 | ```json 101 | { 102 | "gql": "show spaces;" 103 | } 104 | ``` 105 | 106 | **Cookie** is required in the request header to request `exec` api. 107 | 108 | 109 | ```bash 110 | $ curl -X POST \ 111 | -H "Cookie: SameSite=None; common-nsid=bec2e665ba62a13554b617d70de8b9b9" \ 112 | -d '{"gql": "show spaces;"}' \ 113 | http://127.0.0.1:8080/api/db/exec 114 | ``` 115 | 116 | response: 117 | 118 | ```json 119 | { 120 | "code": 0, 121 | "data": { 122 | "headers": [ 123 | "Name" 124 | ], 125 | "tables": [ 126 | { 127 | "Name": "nba" 128 | } 129 | ], 130 | "timeCost": 4232 131 | }, 132 | "message": "" 133 | } 134 | ``` 135 | 136 | #### Disconnect API #### 137 | 138 | ```bash 139 | $ curl -X POST -H "Cookie:common-nsid=bec2e665ba62a13554b617d70de8b9b9" http://127.0.0.1:8080/api/db/disconnect 140 | ``` 141 | 142 | response: 143 | 144 | ```json 145 | { 146 | "code": 0, 147 | "data": null, 148 | "message": "Disconnect successfully" 149 | } 150 | ``` 151 | 152 | #### Import API #### 153 | 154 | The requested json body 155 | 156 | ```json 157 | { 158 | "configPath": "examples/v2/example.yaml" 159 | } 160 | ``` 161 | 162 | The description of the parameters is as follows. 163 | 164 | | Field | Description | 165 | | ---------- | ------------------------------------------------------------ | 166 | | configPath | `configPath` is a relative path that under the `uploadspath` in `app.conf`. | 167 | | configBody | `configBody` is the detail configuration with JSON format (instead of YAML format).| 168 | 169 | If you choose to use `configPath`, you need to make sure that the config file has been uploaded to `uploadspath`. 170 | 171 | ```bash 172 | $ curl -X POST -d '{"configPath": "./examples/v2/example.yaml","configBody": {}}' http://127.0.0.1:8080/api/task/import 173 | ``` 174 | 175 | If you choose to use `configBody`, you need to set the `configPath` value to `""` and set the `configBody` as JSON format. 176 | 177 | response: 178 | 179 | ```json 180 | { 181 | "code": 0, 182 | "data": [ 183 | "1" 184 | ], 185 | "message": "Import task 1 submit successfully" 186 | } 187 | ``` 188 | 189 | #### Action API #### 190 | 191 | The requested json body 192 | 193 | ```json 194 | { 195 | "taskID": "1", 196 | "taskAction": "actionQuery" 197 | } 198 | ``` 199 | 200 | The description of the parameters is as follows. 201 | 202 | | Field | Description | 203 | | ---------- | ---------------------------------------------------- | 204 | | taskID | Set the task id to do task action | 205 | | taskAction | The task action enums, include: actionQuery, actionQueryAll, actionStop, actionStopAll, etc. | 206 | 207 | ```bash 208 | $ curl -X POST -d '{"taskID": "1", "taskAction": "actionQuery"}' http://127.0.0.1:8080/api/task/import/action 209 | ``` 210 | 211 | response: 212 | 213 | ```json 214 | { 215 | "code": 0, 216 | "data": { 217 | "results": [ 218 | { 219 | "taskID": "1", 220 | "taskStatus": "statusProcessing" 221 | } 222 | ], 223 | "msg": "Task is processing" 224 | }, 225 | "message": "Processing a task action successfully" 226 | } 227 | ``` 228 | 229 | -------------------------------------------------------------------------------- /ccore/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/vesoft-inc/nebula-http-gateway/ccore 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/facebook/fbthrift v0.31.1-0.20211129061412-801ed7f9f295 7 | github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b 8 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect 9 | ) 10 | -------------------------------------------------------------------------------- /ccore/go.sum: -------------------------------------------------------------------------------- 1 | github.com/facebook/fbthrift v0.31.1-0.20211129061412-801ed7f9f295 h1:ZA+qQ3d2In0RNzVpk+D/nq1sjDSv+s1Wy2zrAPQAmsg= 2 | github.com/facebook/fbthrift v0.31.1-0.20211129061412-801ed7f9f295/go.mod h1:2tncLx5rmw69e5kMBv/yJneERbzrr1yr5fdlnTbu8lU= 3 | github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= 4 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 5 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 6 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 7 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 8 | github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b h1:gQZ0qzfKHQIybLANtM3mBXNUtOfsCFXeTsnBqCsx1KM= 9 | github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= 10 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 11 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 12 | -------------------------------------------------------------------------------- /ccore/nebula/alias.go: -------------------------------------------------------------------------------- 1 | package nebula 2 | 3 | import ( 4 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 5 | ) 6 | 7 | type ( 8 | Version = types.Version 9 | AuthResponse = types.AuthResponse 10 | ExecutionResponse = types.ExecutionResponse 11 | ) 12 | 13 | var ( 14 | versionAuto = Version("auto") 15 | 16 | Version2_5 = types.Version2_5 17 | Version2_6 = types.Version2_6 18 | Version3_0 = types.Version3_0 19 | 20 | supportedVersions = []Version{ 21 | Version3_0, 22 | Version2_6, 23 | Version2_5, 24 | } 25 | ) 26 | -------------------------------------------------------------------------------- /ccore/nebula/client.go: -------------------------------------------------------------------------------- 1 | package nebula 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 7 | nerrors "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/errors" 8 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 9 | ) 10 | 11 | type ( 12 | // TODO: add client pool management 13 | 14 | Client interface { 15 | Graph() GraphClient 16 | Meta() MetaClient 17 | StorageAdmin() StorageAdminClient 18 | Factory() Factory 19 | Version() Version 20 | } 21 | 22 | ConnectionInfo struct { 23 | GraphEndpoints []string 24 | MetaEndpoints []string 25 | StorageAdminEndpoints []string 26 | GraphAccount Account 27 | } 28 | 29 | Account struct { 30 | Username string 31 | Password string 32 | } 33 | 34 | defaultClient struct { 35 | o Options 36 | driver types.Driver 37 | initDriverOnce sync.Once 38 | graph *driverGraph 39 | meta *driverMeta 40 | storageAdmin *driverStorageAdmin 41 | } 42 | ) 43 | 44 | func NewClient(info ConnectionInfo, opts ...Option) (Client, error) { 45 | o := defaultOptions() 46 | for _, opt := range opts { 47 | opt(&o) 48 | } 49 | o.complete() 50 | if err := o.validate(); err != nil { 51 | return nil, err 52 | } 53 | 54 | return &defaultClient{ 55 | o: o, 56 | graph: newDriverGraph(info.GraphEndpoints, info.GraphAccount.Username, info.GraphAccount.Password, &o.graph), 57 | meta: newDriverMeta(info.MetaEndpoints, &o.meta), 58 | storageAdmin: newDriverStorageAdmin(info.StorageAdminEndpoints, &o.storageAdmin), 59 | }, nil 60 | } 61 | 62 | func (c *defaultClient) Graph() GraphClient { 63 | return (*defaultGraphClient)(c) 64 | } 65 | 66 | func (c *defaultClient) Meta() MetaClient { 67 | return (*defaultMetaClient)(c) 68 | } 69 | 70 | func (c *defaultClient) StorageAdmin() StorageAdminClient { 71 | return (*defaultStorageAdminClient)(c) 72 | } 73 | 74 | func (c *defaultClient) Factory() Factory { 75 | f, _ := NewFactory(WithVersion(c.o.version)) 76 | return f 77 | } 78 | 79 | func (c *defaultClient) Version() Version { 80 | return c.o.version 81 | } 82 | 83 | func (c *defaultClient) initDriver(checkFn func(types.Driver) error) error { 84 | if c.o.version != versionAuto { 85 | driver, err := types.GetDriver(c.o.version) 86 | if err != nil { 87 | return err 88 | } 89 | if err = checkFn(driver); err != nil { 90 | return err 91 | } 92 | c.driver = driver 93 | return nil 94 | } 95 | for _, v := range c.o.autoVersions { 96 | driver, err := types.GetDriver(v) 97 | if err != nil { 98 | return err 99 | } 100 | if err = checkFn(driver); err != nil { 101 | if nerrors.IsCodeError(err, nerrors.ErrorCode_E_CLIENT_SERVER_INCOMPATIBLE) { 102 | continue 103 | } 104 | if e, ok := err.(thrift.ApplicationException); ok && e.TypeID() == thrift.WRONG_METHOD_NAME { 105 | continue 106 | } 107 | return err 108 | } 109 | c.driver = driver 110 | c.o.version = v 111 | return nil 112 | } 113 | return nerrors.ErrUnsupportedVersion 114 | } 115 | -------------------------------------------------------------------------------- /ccore/nebula/client_graph.go: -------------------------------------------------------------------------------- 1 | package nebula 2 | 3 | import ( 4 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 5 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/wrapper" 6 | ) 7 | 8 | type ( 9 | GraphClient interface { 10 | Open() error 11 | Authenticate(username, password string) (AuthResponse, error) 12 | Execute(stmt []byte) (ExecutionResponse, error) 13 | ExecuteJson(stmt []byte) ([]byte, error) 14 | ExecuteWithParameter(stmt []byte, params types.ParameterMap) (ExecutionResponse, error) 15 | Close() error 16 | Factory() Factory 17 | Version() Version 18 | GetTimezoneInfo() types.TimezoneInfo 19 | } 20 | 21 | defaultGraphClient defaultClient 22 | ) 23 | 24 | func NewGraphClient(endpoints []string, username, password string, opts ...Option) (GraphClient, error) { 25 | c, err := NewClient(ConnectionInfo{ 26 | GraphEndpoints: endpoints, 27 | GraphAccount: Account{ 28 | Username: username, 29 | Password: password, 30 | }, 31 | }, opts...) 32 | if err != nil { 33 | return nil, err 34 | } 35 | return c.Graph(), nil 36 | } 37 | 38 | func (c *defaultGraphClient) GetTimezoneInfo() types.TimezoneInfo { 39 | return c.graph.GetTimezoneInfo() 40 | } 41 | 42 | func (c *defaultGraphClient) Open() error { 43 | return c.defaultClient().initDriver(func(driver types.Driver) error { 44 | return c.graph.open(driver) 45 | }) 46 | } 47 | 48 | func (c *defaultGraphClient) Authenticate(username, password string) (AuthResponse, error) { 49 | return c.graph.Authenticate(username, password) 50 | } 51 | 52 | func (c *defaultGraphClient) Execute(stmt []byte) (ExecutionResponse, error) { 53 | return c.graph.Execute(c.graph.sessionId, stmt) 54 | } 55 | 56 | func (c *defaultGraphClient) ExecuteJson(stmt []byte) ([]byte, error) { 57 | return c.graph.ExecuteJson(c.graph.sessionId, stmt) 58 | } 59 | 60 | func (c *defaultGraphClient) ExecuteWithParameter(stmt []byte, params types.ParameterMap) (ExecutionResponse, error) { 61 | if len(params) == 0 { 62 | return c.Execute(stmt) 63 | } 64 | // wrap the map of interface{} to map of types.Value 65 | paramsMap := make(map[string]types.Value) 66 | for k, v := range params { 67 | nv, er := wrapper.WrapValue(v, c.Factory()) 68 | if er != nil { 69 | return nil, er 70 | } 71 | paramsMap[k] = nv 72 | } 73 | return c.graph.ExecuteWithParameter(c.graph.sessionId, stmt, paramsMap) 74 | } 75 | 76 | func (c *defaultGraphClient) Close() error { 77 | return c.graph.close() 78 | } 79 | 80 | func (c *defaultGraphClient) Factory() Factory { 81 | return c.defaultClient().Factory() 82 | } 83 | 84 | func (c *defaultGraphClient) Version() Version { 85 | return c.defaultClient().Version() 86 | } 87 | 88 | func (c *defaultGraphClient) defaultClient() *defaultClient { 89 | return (*defaultClient)(c) 90 | } 91 | -------------------------------------------------------------------------------- /ccore/nebula/client_meta.go: -------------------------------------------------------------------------------- 1 | package nebula 2 | 3 | import ( 4 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 5 | 6 | nerrors "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/errors" 7 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 8 | ) 9 | 10 | type ( 11 | MetaClient interface { 12 | Open() error 13 | AddHosts(endpoints []string) (types.MetaBaser, error) 14 | AddHostsIntoZone(zone string, endpoints []string, isNew bool) (types.MetaBaser, error) 15 | DropHosts(endpoints []string) (types.MetaBaser, error) 16 | ListSpaces() (types.Spaces, error) 17 | BalanceData(space string) (types.Balancer, error) 18 | BalanceLeader(space string) (types.Balancer, error) 19 | BalanceDataRemove(space string, endpoints []string) (types.Balancer, error) 20 | ListHosts() (types.Hosts, error) 21 | ListZones() (types.Zones, error) 22 | Close() error 23 | } 24 | 25 | defaultMetaClient defaultClient 26 | ) 27 | 28 | func NewMetaClient(endpoints []string, opts ...Option) (MetaClient, error) { 29 | c, err := NewClient(ConnectionInfo{ 30 | MetaEndpoints: endpoints, 31 | }, opts...) 32 | if err != nil { 33 | return nil, err 34 | } 35 | return c.Meta(), nil 36 | } 37 | 38 | func (c *defaultMetaClient) Open() error { 39 | return c.defaultClient().initDriver(func(driver types.Driver) error { 40 | return c.openRetry(driver) 41 | }) 42 | } 43 | 44 | func (c *defaultMetaClient) ListHosts() (resp types.Hosts, err error) { 45 | retryErr := c.retryDo(func() (types.MetaBaser, error) { 46 | resp, err = c.meta.ListHosts() 47 | return resp, err 48 | }) 49 | if retryErr != nil { 50 | return nil, retryErr 51 | } 52 | 53 | return 54 | } 55 | 56 | func (c *defaultMetaClient) ListZones() (resp types.Zones, err error) { 57 | retryErr := c.retryDo(func() (types.MetaBaser, error) { 58 | resp, err = c.meta.ListZones() 59 | return resp, err 60 | }) 61 | if retryErr != nil { 62 | return nil, retryErr 63 | } 64 | 65 | return 66 | } 67 | 68 | func (c *defaultMetaClient) Close() error { 69 | return c.meta.close() 70 | } 71 | 72 | func (c *defaultMetaClient) AddHosts(endpoints []string) (resp types.MetaBaser, err error) { 73 | retryErr := c.retryDo(func() (types.MetaBaser, error) { 74 | resp, err = c.meta.AddHosts(endpoints) 75 | return resp, err 76 | }) 77 | if retryErr != nil { 78 | return nil, retryErr 79 | } 80 | 81 | return 82 | } 83 | 84 | func (c *defaultMetaClient) AddHostsIntoZone(zone string, endpoints []string, isNew bool) (resp types.MetaBaser, err error) { 85 | retryErr := c.retryDo(func() (types.MetaBaser, error) { 86 | resp, err = c.meta.AddHostsIntoZone(zone, endpoints, isNew) 87 | return resp, err 88 | }) 89 | if retryErr != nil { 90 | return nil, retryErr 91 | } 92 | 93 | return 94 | } 95 | 96 | func (c *defaultMetaClient) DropHosts(endpoints []string) (resp types.MetaBaser, err error) { 97 | retryErr := c.retryDo(func() (types.MetaBaser, error) { 98 | resp, err = c.meta.DropHosts(endpoints) 99 | return resp, err 100 | }) 101 | if retryErr != nil { 102 | return nil, retryErr 103 | } 104 | 105 | return 106 | } 107 | 108 | func (c *defaultMetaClient) ListSpaces() (resp types.Spaces, err error) { 109 | retryErr := c.retryDo(func() (types.MetaBaser, error) { 110 | resp, err = c.meta.ListSpaces() 111 | return resp, err 112 | }) 113 | if retryErr != nil { 114 | return nil, retryErr 115 | } 116 | 117 | return 118 | } 119 | 120 | func (c *defaultMetaClient) BalanceData(space string) (resp types.Balancer, err error) { 121 | retryErr := c.retryDo(func() (types.MetaBaser, error) { 122 | resp, err = c.meta.Balance(types.BalanceReq{ 123 | Cmd: types.BalanceData, 124 | Space: space, 125 | }) 126 | return resp, err 127 | }) 128 | if retryErr != nil { 129 | return nil, retryErr 130 | } 131 | 132 | return 133 | } 134 | 135 | func (c *defaultMetaClient) BalanceLeader(space string) (resp types.Balancer, err error) { 136 | retryErr := c.retryDo(func() (types.MetaBaser, error) { 137 | resp, err = c.meta.Balance(types.BalanceReq{ 138 | Cmd: types.BalanceLeader, 139 | Space: space, 140 | }) 141 | return resp, err 142 | }) 143 | if retryErr != nil { 144 | return nil, retryErr 145 | } 146 | 147 | return 148 | } 149 | 150 | func (c *defaultMetaClient) BalanceDataRemove(space string, endpoints []string) (resp types.Balancer, err error) { 151 | retryErr := c.retryDo(func() (types.MetaBaser, error) { 152 | resp, err = c.meta.Balance(types.BalanceReq{ 153 | Cmd: types.BalanceDataRemove, 154 | Space: space, 155 | HostsToRemove: endpoints, 156 | }) 157 | return resp, err 158 | }) 159 | 160 | if retryErr != nil { 161 | return nil, retryErr 162 | } 163 | 164 | return 165 | } 166 | 167 | func (c *defaultMetaClient) defaultClient() *defaultClient { 168 | return (*defaultClient)(c) 169 | } 170 | 171 | func (c *defaultMetaClient) retryDo(fn func() (types.MetaBaser, error)) error { 172 | resp, err := fn() 173 | if err != nil { 174 | // check if transport exception 175 | if err = c.reconnect(err); err != nil { 176 | return err 177 | } 178 | resp, err = fn() 179 | if err != nil { 180 | return err 181 | } 182 | } 183 | // check if leader change 184 | if resp.GetCode() == nerrors.ErrorCode_E_LEADER_CHANGED { 185 | if err = c.updateLeader(resp.GetLeader()); err != nil { 186 | return err 187 | } 188 | if _, err = fn(); err != nil { 189 | return err 190 | } 191 | } 192 | return nil 193 | } 194 | 195 | func (c *defaultMetaClient) updateLeader(endpoint string) error { 196 | if err := c.meta.connection.SetEndpointIfExists(endpoint); err != nil { 197 | return err 198 | } 199 | return c.openRetry(c.driver) 200 | } 201 | 202 | func (c *defaultMetaClient) reconnect(err error) error { 203 | if _, ok := err.(thrift.TransportException); !ok { 204 | return err 205 | } 206 | return c.openRetry(c.driver) 207 | } 208 | 209 | func (c *defaultMetaClient) openRetry(driver types.Driver) error { 210 | n := c.meta.connection.GetEndpointsLen() 211 | for i := 0; i < n; i++ { 212 | _ = c.meta.close() 213 | 214 | err := c.meta.open(driver) 215 | if err == nil { 216 | return nil 217 | } 218 | c.meta.connection.UpdateNextIndex() // update nextIndex when connect failed 219 | } 220 | return nerrors.ErrNoValidMetaEndpoint 221 | } 222 | -------------------------------------------------------------------------------- /ccore/nebula/client_storage_admin.go: -------------------------------------------------------------------------------- 1 | package nebula 2 | 3 | import "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 4 | 5 | type ( 6 | StorageAdminClient interface { 7 | Open() error 8 | Close() error 9 | } 10 | 11 | defaultStorageAdminClient defaultClient 12 | ) 13 | 14 | func NewStorageAdminClient(endpoints []string, opts ...Option) (StorageAdminClient, error) { 15 | c, err := NewClient(ConnectionInfo{ 16 | StorageAdminEndpoints: endpoints, 17 | }, opts...) 18 | if err != nil { 19 | return nil, err 20 | } 21 | return c.StorageAdmin(), nil 22 | } 23 | 24 | func (c *defaultStorageAdminClient) Open() error { 25 | return c.defaultClient().initDriver(func(driver types.Driver) error { 26 | return c.storageAdmin.open(driver) 27 | }) 28 | } 29 | 30 | func (c *defaultStorageAdminClient) Close() error { 31 | return c.storageAdmin.close() 32 | } 33 | 34 | func (c *defaultStorageAdminClient) defaultClient() *defaultClient { 35 | return (*defaultClient)(c) 36 | } 37 | -------------------------------------------------------------------------------- /ccore/nebula/driver.go: -------------------------------------------------------------------------------- 1 | package nebula 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 7 | nerrors "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/errors" 8 | _ "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/driver/v2_5" 9 | _ "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/driver/v2_6" 10 | _ "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/driver/v3_0" 11 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 12 | ) 13 | 14 | type ( 15 | driverGraph struct { 16 | types.GraphClientDriver 17 | connection *connectionMu 18 | username string 19 | password string 20 | sessionId int64 21 | timezone types.TimezoneInfo 22 | } 23 | 24 | driverMeta struct { 25 | types.MetaClientDriver 26 | connection *connectionMu 27 | } 28 | 29 | driverStorageAdmin struct { 30 | types.StorageAdminClientDriver 31 | connection *connectionMu 32 | } 33 | 34 | connectionMu struct { 35 | o *socketOptions 36 | mu sync.Mutex 37 | endpoints []string 38 | nextIndex int 39 | } 40 | 41 | driverFactory struct { 42 | types.FactoryDriver 43 | } 44 | ) 45 | 46 | func newDriverGraph(endpoints []string, username, password string, o *socketOptions) *driverGraph { 47 | return &driverGraph{ 48 | connection: newConnectionMu(endpoints, o), 49 | username: username, 50 | password: password, 51 | } 52 | } 53 | 54 | func newDriverMeta(endpoints []string, o *socketOptions) *driverMeta { 55 | return &driverMeta{ 56 | connection: newConnectionMu(endpoints, o), 57 | } 58 | } 59 | 60 | func newDriverStorageAdmin(endpoints []string, o *socketOptions) *driverStorageAdmin { 61 | return &driverStorageAdmin{ 62 | connection: newConnectionMu(endpoints, o), 63 | } 64 | } 65 | 66 | func newConnectionMu(endpoints []string, o *socketOptions) *connectionMu { 67 | return &connectionMu{ 68 | o: o, 69 | endpoints: endpoints, 70 | } 71 | } 72 | 73 | func newDriverFactory() *driverFactory { 74 | return &driverFactory{} 75 | } 76 | 77 | func (d *driverGraph) open(driver types.Driver) error { 78 | if d.GraphClientDriver != nil { 79 | return nil 80 | } 81 | 82 | transport, pf, err := d.connection.connect() 83 | if err != nil { 84 | return err 85 | } 86 | 87 | graphClientDriver := driver.NewGraphClientDriver(transport, pf) 88 | 89 | if err = graphClientDriver.Open(); err != nil { 90 | return err 91 | } 92 | 93 | if err = graphClientDriver.VerifyClientVersion(); err != nil { 94 | _ = graphClientDriver.Close() 95 | return err 96 | } 97 | 98 | resp, err := graphClientDriver.Authenticate(d.username, d.password) 99 | if err != nil { 100 | _ = graphClientDriver.Close() 101 | return err 102 | } 103 | 104 | sessionId := resp.SessionID() 105 | if sessionId == nil { 106 | panic("sessionId can not be nil after authenticate") 107 | } 108 | d.sessionId = *sessionId 109 | d.timezone = resp.GetTimezoneInfo() 110 | d.GraphClientDriver = graphClientDriver 111 | return nil 112 | } 113 | 114 | func (d *driverGraph) GetTimezoneInfo() types.TimezoneInfo { 115 | return d.timezone 116 | } 117 | 118 | func (d *driverGraph) close() error { 119 | if d.GraphClientDriver != nil { 120 | d.GraphClientDriver.Signout(d.sessionId) 121 | if err := d.GraphClientDriver.Close(); err != nil { 122 | return err 123 | } 124 | } 125 | return nil 126 | } 127 | 128 | func (d *driverMeta) open(driver types.Driver) error { 129 | transport, pf, err := d.connection.connect() 130 | if err != nil { 131 | return err 132 | } 133 | 134 | metaClientDriver := driver.NewMetaClientDriver(transport, pf) 135 | 136 | if err = metaClientDriver.Open(); err != nil { 137 | return err 138 | } 139 | 140 | if err = metaClientDriver.VerifyClientVersion(); err != nil { 141 | _ = metaClientDriver.Close() 142 | return err 143 | } 144 | 145 | d.MetaClientDriver = metaClientDriver 146 | return nil 147 | } 148 | 149 | func (d *driverMeta) close() error { 150 | if d.MetaClientDriver != nil { 151 | if err := d.MetaClientDriver.Close(); err != nil { 152 | return err 153 | } 154 | } 155 | return nil 156 | } 157 | 158 | func (d *driverStorageAdmin) open(driver types.Driver) error { 159 | if d.StorageAdminClientDriver != nil { 160 | return nil 161 | } 162 | 163 | transport, pf, err := d.connection.connect() 164 | if err != nil { 165 | return err 166 | } 167 | 168 | storageAdminClientDriver := driver.NewStorageClientDriver(transport, pf) 169 | 170 | if err = storageAdminClientDriver.Open(); err != nil { 171 | return err 172 | } 173 | 174 | d.StorageAdminClientDriver = storageAdminClientDriver 175 | return nil 176 | } 177 | 178 | func (d *driverStorageAdmin) close() error { 179 | if d.StorageAdminClientDriver != nil { 180 | if err := d.StorageAdminClientDriver.Close(); err != nil { 181 | return err 182 | } 183 | } 184 | return nil 185 | } 186 | 187 | func (c *connectionMu) connect() (thrift.Transport, thrift.ProtocolFactory, error) { 188 | if len(c.endpoints) == 0 { 189 | return nil, nil, nerrors.ErrNoEndpoints 190 | } 191 | 192 | return c.buildThriftTransport(c.endpoints[c.nextIndex]) 193 | } 194 | 195 | func (c *connectionMu) buildThriftTransport(endpoint string) (thrift.Transport, thrift.ProtocolFactory, error) { 196 | transport, err := func() (thrift.Transport, error) { 197 | if c.o.tlsConfig == nil { 198 | return thrift.NewSocket(thrift.SocketTimeout(c.o.timeout), thrift.SocketAddr(endpoint)) 199 | } 200 | return thrift.NewSSLSocketTimeout(endpoint, c.o.tlsConfig, c.o.timeout) 201 | }() 202 | if err != nil { 203 | return nil, nil, err 204 | } 205 | 206 | bufferedTranFactory := thrift.NewBufferedTransportFactory(c.o.bufferSize) 207 | transport = thrift.NewFramedTransportMaxLength(bufferedTranFactory.GetTransport(transport), c.o.frameMaxLength) 208 | pf := thrift.NewBinaryProtocolFactoryDefault() 209 | 210 | return transport, pf, nil 211 | } 212 | 213 | func (c *connectionMu) UpdateNextIndex() { 214 | c.mu.Lock() 215 | defer c.mu.Unlock() 216 | c.nextIndex = (c.nextIndex + 1) % c.GetEndpointsLen() 217 | } 218 | 219 | func (c *connectionMu) SetEndpointIfExists(endpoint string) error { 220 | c.mu.Lock() 221 | defer c.mu.Unlock() 222 | for i, ep := range c.endpoints { 223 | if ep == endpoint { 224 | c.nextIndex = i 225 | return nil 226 | } 227 | } 228 | return nerrors.ErrUnknownMetaEndpoint 229 | } 230 | 231 | func (c *connectionMu) GetEndpointsLen() int { 232 | return len(c.endpoints) 233 | } 234 | -------------------------------------------------------------------------------- /ccore/nebula/error.go: -------------------------------------------------------------------------------- 1 | package nebula 2 | -------------------------------------------------------------------------------- /ccore/nebula/errors/error_code.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | stderrors "errors" 5 | "fmt" 6 | ) 7 | 8 | type ( 9 | ErrorCode int64 10 | 11 | codeError struct { 12 | errorCode ErrorCode 13 | errorMsg string 14 | } 15 | 16 | CodeError interface { 17 | error 18 | GetErrorCode() ErrorCode 19 | GetErrorMsg() string 20 | } 21 | ) 22 | 23 | func AsCodeError(err error) (CodeError, bool) { 24 | if e := new(codeError); stderrors.As(err, &e) { 25 | return e, true 26 | } 27 | return nil, false 28 | } 29 | 30 | func IsCodeError(err error, c ...ErrorCode) bool { 31 | ce, ok := AsCodeError(err) 32 | if !ok { 33 | return false 34 | } 35 | switch len(c) { 36 | case 0: 37 | return true 38 | case 1: 39 | return ce.GetErrorCode() == c[0] 40 | default: 41 | return false 42 | } 43 | } 44 | 45 | func NewCodeError(errorCode ErrorCode, errorMsg string) error { 46 | return &codeError{ 47 | errorCode: errorCode, 48 | errorMsg: errorMsg, 49 | } 50 | } 51 | 52 | func (e *codeError) Error() string { 53 | return fmt.Sprintf("%d:%s", int64(e.errorCode), e.errorMsg) 54 | } 55 | 56 | func (e *codeError) GetErrorCode() ErrorCode { 57 | return e.errorCode 58 | } 59 | 60 | func (e *codeError) GetErrorMsg() string { 61 | return e.errorMsg 62 | } 63 | 64 | const ( 65 | ErrorCode_SUCCEEDED ErrorCode = 0 66 | ErrorCode_E_DISCONNECTED ErrorCode = -1 67 | ErrorCode_E_FAIL_TO_CONNECT ErrorCode = -2 68 | ErrorCode_E_RPC_FAILURE ErrorCode = -3 69 | ErrorCode_E_LEADER_CHANGED ErrorCode = -4 70 | ErrorCode_E_SPACE_NOT_FOUND ErrorCode = -5 71 | ErrorCode_E_TAG_NOT_FOUND ErrorCode = -6 72 | ErrorCode_E_EDGE_NOT_FOUND ErrorCode = -7 73 | ErrorCode_E_INDEX_NOT_FOUND ErrorCode = -8 74 | ErrorCode_E_EDGE_PROP_NOT_FOUND ErrorCode = -9 75 | ErrorCode_E_TAG_PROP_NOT_FOUND ErrorCode = -10 76 | ErrorCode_E_ROLE_NOT_FOUND ErrorCode = -11 77 | ErrorCode_E_CONFIG_NOT_FOUND ErrorCode = -12 78 | ErrorCode_E_GROUP_NOT_FOUND ErrorCode = -13 79 | ErrorCode_E_ZONE_NOT_FOUND ErrorCode = -14 80 | ErrorCode_E_LISTENER_NOT_FOUND ErrorCode = -15 81 | ErrorCode_E_PART_NOT_FOUND ErrorCode = -16 82 | ErrorCode_E_KEY_NOT_FOUND ErrorCode = -17 83 | ErrorCode_E_USER_NOT_FOUND ErrorCode = -18 84 | ErrorCode_E_STATS_NOT_FOUND ErrorCode = -19 85 | ErrorCode_E_BACKUP_FAILED ErrorCode = -24 86 | ErrorCode_E_BACKUP_EMPTY_TABLE ErrorCode = -25 87 | ErrorCode_E_BACKUP_TABLE_FAILED ErrorCode = -26 88 | ErrorCode_E_PARTIAL_RESULT ErrorCode = -27 89 | ErrorCode_E_REBUILD_INDEX_FAILED ErrorCode = -28 90 | ErrorCode_E_INVALID_PASSWORD ErrorCode = -29 91 | ErrorCode_E_FAILED_GET_ABS_PATH ErrorCode = -30 92 | ErrorCode_E_BAD_USERNAME_PASSWORD ErrorCode = -1001 93 | ErrorCode_E_SESSION_INVALID ErrorCode = -1002 94 | ErrorCode_E_SESSION_TIMEOUT ErrorCode = -1003 95 | ErrorCode_E_SYNTAX_ERROR ErrorCode = -1004 96 | ErrorCode_E_EXECUTION_ERROR ErrorCode = -1005 97 | ErrorCode_E_STATEMENT_EMPTY ErrorCode = -1006 98 | ErrorCode_E_BAD_PERMISSION ErrorCode = -1008 99 | ErrorCode_E_SEMANTIC_ERROR ErrorCode = -1009 100 | ErrorCode_E_TOO_MANY_CONNECTIONS ErrorCode = -1010 101 | ErrorCode_E_PARTIAL_SUCCEEDED ErrorCode = -1011 102 | ErrorCode_E_NO_HOSTS ErrorCode = -2001 103 | ErrorCode_E_EXISTED ErrorCode = -2002 104 | ErrorCode_E_INVALID_HOST ErrorCode = -2003 105 | ErrorCode_E_UNSUPPORTED ErrorCode = -2004 106 | ErrorCode_E_NOT_DROP ErrorCode = -2005 107 | ErrorCode_E_BALANCER_RUNNING ErrorCode = -2006 108 | ErrorCode_E_CONFIG_IMMUTABLE ErrorCode = -2007 109 | ErrorCode_E_CONFLICT ErrorCode = -2008 110 | ErrorCode_E_INVALID_PARM ErrorCode = -2009 111 | ErrorCode_E_WRONGCLUSTER ErrorCode = -2010 112 | ErrorCode_E_STORE_FAILURE ErrorCode = -2021 113 | ErrorCode_E_STORE_SEGMENT_ILLEGAL ErrorCode = -2022 114 | ErrorCode_E_BAD_BALANCE_PLAN ErrorCode = -2023 115 | ErrorCode_E_BALANCED ErrorCode = -2024 116 | ErrorCode_E_NO_RUNNING_BALANCE_PLAN ErrorCode = -2025 117 | ErrorCode_E_NO_VALID_HOST ErrorCode = -2026 118 | ErrorCode_E_CORRUPTTED_BALANCE_PLAN ErrorCode = -2027 119 | ErrorCode_E_NO_INVALID_BALANCE_PLAN ErrorCode = -2028 120 | ErrorCode_E_IMPROPER_ROLE ErrorCode = -2030 121 | ErrorCode_E_INVALID_PARTITION_NUM ErrorCode = -2031 122 | ErrorCode_E_INVALID_REPLICA_FACTOR ErrorCode = -2032 123 | ErrorCode_E_INVALID_CHARSET ErrorCode = -2033 124 | ErrorCode_E_INVALID_COLLATE ErrorCode = -2034 125 | ErrorCode_E_CHARSET_COLLATE_NOT_MATCH ErrorCode = -2035 126 | ErrorCode_E_SNAPSHOT_FAILURE ErrorCode = -2040 127 | ErrorCode_E_BLOCK_WRITE_FAILURE ErrorCode = -2041 128 | ErrorCode_E_REBUILD_INDEX_FAILURE ErrorCode = -2042 129 | ErrorCode_E_INDEX_WITH_TTL ErrorCode = -2043 130 | ErrorCode_E_ADD_JOB_FAILURE ErrorCode = -2044 131 | ErrorCode_E_STOP_JOB_FAILURE ErrorCode = -2045 132 | ErrorCode_E_SAVE_JOB_FAILURE ErrorCode = -2046 133 | ErrorCode_E_BALANCER_FAILURE ErrorCode = -2047 134 | ErrorCode_E_JOB_NOT_FINISHED ErrorCode = -2048 135 | ErrorCode_E_TASK_REPORT_OUT_DATE ErrorCode = -2049 136 | ErrorCode_E_JOB_NOT_IN_SPACE ErrorCode = -2050 137 | ErrorCode_E_INVALID_JOB ErrorCode = -2065 138 | ErrorCode_E_BACKUP_BUILDING_INDEX ErrorCode = -2066 139 | ErrorCode_E_BACKUP_SPACE_NOT_FOUND ErrorCode = -2067 140 | ErrorCode_E_RESTORE_FAILURE ErrorCode = -2068 141 | ErrorCode_E_SESSION_NOT_FOUND ErrorCode = -2069 142 | ErrorCode_E_LIST_CLUSTER_FAILURE ErrorCode = -2070 143 | ErrorCode_E_LIST_CLUSTER_GET_ABS_PATH_FAILURE ErrorCode = -2071 144 | ErrorCode_E_GET_META_DIR_FAILURE ErrorCode = -2072 145 | ErrorCode_E_QUERY_NOT_FOUND ErrorCode = -2073 146 | ErrorCode_E_CONSENSUS_ERROR ErrorCode = -3001 147 | ErrorCode_E_KEY_HAS_EXISTS ErrorCode = -3002 148 | ErrorCode_E_DATA_TYPE_MISMATCH ErrorCode = -3003 149 | ErrorCode_E_INVALID_FIELD_VALUE ErrorCode = -3004 150 | ErrorCode_E_INVALID_OPERATION ErrorCode = -3005 151 | ErrorCode_E_NOT_NULLABLE ErrorCode = -3006 152 | ErrorCode_E_FIELD_UNSET ErrorCode = -3007 153 | ErrorCode_E_OUT_OF_RANGE ErrorCode = -3008 154 | ErrorCode_E_ATOMIC_OP_FAILED ErrorCode = -3009 155 | ErrorCode_E_DATA_CONFLICT_ERROR ErrorCode = -3010 156 | ErrorCode_E_WRITE_STALLED ErrorCode = -3011 157 | ErrorCode_E_IMPROPER_DATA_TYPE ErrorCode = -3021 158 | ErrorCode_E_INVALID_SPACEVIDLEN ErrorCode = -3022 159 | ErrorCode_E_INVALID_FILTER ErrorCode = -3031 160 | ErrorCode_E_INVALID_UPDATER ErrorCode = -3032 161 | ErrorCode_E_INVALID_STORE ErrorCode = -3033 162 | ErrorCode_E_INVALID_PEER ErrorCode = -3034 163 | ErrorCode_E_RETRY_EXHAUSTED ErrorCode = -3035 164 | ErrorCode_E_TRANSFER_LEADER_FAILED ErrorCode = -3036 165 | ErrorCode_E_INVALID_STAT_TYPE ErrorCode = -3037 166 | ErrorCode_E_INVALID_VID ErrorCode = -3038 167 | ErrorCode_E_NO_TRANSFORMED ErrorCode = -3039 168 | ErrorCode_E_LOAD_META_FAILED ErrorCode = -3040 169 | ErrorCode_E_FAILED_TO_CHECKPOINT ErrorCode = -3041 170 | ErrorCode_E_CHECKPOINT_BLOCKED ErrorCode = -3042 171 | ErrorCode_E_FILTER_OUT ErrorCode = -3043 172 | ErrorCode_E_INVALID_DATA ErrorCode = -3044 173 | ErrorCode_E_MUTATE_EDGE_CONFLICT ErrorCode = -3045 174 | ErrorCode_E_MUTATE_TAG_CONFLICT ErrorCode = -3046 175 | ErrorCode_E_OUTDATED_LOCK ErrorCode = -3047 176 | ErrorCode_E_INVALID_TASK_PARA ErrorCode = -3051 177 | ErrorCode_E_USER_CANCEL ErrorCode = -3052 178 | ErrorCode_E_TASK_EXECUTION_FAILED ErrorCode = -3053 179 | ErrorCode_E_PLAN_IS_KILLED ErrorCode = -3060 180 | ErrorCode_E_NO_TERM ErrorCode = -3070 181 | ErrorCode_E_OUTDATED_TERM ErrorCode = -3071 182 | ErrorCode_E_OUTDATED_EDGE ErrorCode = -3072 183 | ErrorCode_E_WRITE_WRITE_CONFLICT ErrorCode = -3073 184 | ErrorCode_E_CLIENT_SERVER_INCOMPATIBLE ErrorCode = -3061 185 | ErrorCode_E_UNKNOWN ErrorCode = -8000 186 | ) 187 | -------------------------------------------------------------------------------- /ccore/nebula/errors/errors.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrUnsupportedVersion = errors.New("unsupported version") 7 | ErrUnsupported = errors.New("unsupported") 8 | ErrNoEndpoints = errors.New("no endpoints") 9 | ErrNoJobStats = errors.New("no job stats") 10 | ErrUnknownMetaEndpoint = errors.New("unknown meta endpoint to update connection") 11 | ErrNoValidMetaEndpoint = errors.New("no valid meta endpoint to connect") 12 | ) 13 | -------------------------------------------------------------------------------- /ccore/nebula/examples/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "strings" 7 | 8 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula" 9 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 10 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/wrapper" 11 | ) 12 | 13 | type TestCase struct { 14 | version nebula.Version 15 | host string 16 | } 17 | 18 | func main() { 19 | testCases := []TestCase{ 20 | {nebula.Version2_5, "192.168.8.157:9669"}, 21 | {nebula.Version2_6, "192.168.8.157:9669"}, 22 | {nebula.Version3_0, "192.168.8.167:9669"}, 23 | } 24 | for _, testCase := range testCases { 25 | var ( 26 | c nebula.Client 27 | gc nebula.GraphClient 28 | err error 29 | 30 | version = testCase.version 31 | host = testCase.host 32 | username = "root" 33 | password = "123" 34 | ) 35 | { // use nebula.NewClient 36 | c, err = nebula.NewClient(nebula.ConnectionInfo{ 37 | GraphEndpoints: []string{host}, 38 | GraphAccount: nebula.Account{ 39 | Username: username, 40 | Password: password, 41 | }, 42 | }, nebula.WithVersion(version)) 43 | if err != nil { 44 | panic(fmt.Sprintf("%s %+v", version, err)) 45 | } 46 | if err = c.Graph().Open(); err != nil { 47 | panic(err) 48 | } 49 | 50 | executeExample(c.Graph()) 51 | 52 | if err = c.Graph().Close(); err != nil { 53 | panic(err) 54 | } 55 | log.Println("basic execute example finished") 56 | } 57 | { // use nebula.NewGraphClient 58 | log.Println("execute with params example...") 59 | gc, err = nebula.NewGraphClient([]string{host}, username, password, nebula.WithVersion(version)) 60 | if err != nil { 61 | panic(fmt.Sprintf("%s %+v", version, err)) 62 | } 63 | if err = gc.Open(); err != nil { 64 | panic(err) 65 | } 66 | 67 | executeWithParamsExample(gc) 68 | 69 | if err = gc.Close(); err != nil { 70 | panic(err) 71 | } 72 | log.Println("execute with params example finished") 73 | } 74 | 75 | factoryExample(c) 76 | } 77 | } 78 | 79 | func executeExample(gc nebula.GraphClient) { 80 | { 81 | // Prepare the query 82 | createSchema := "CREATE SPACE IF NOT EXISTS basic_example_space(vid_type=FIXED_STRING(20)); " + 83 | "USE basic_example_space;" + 84 | "CREATE TAG IF NOT EXISTS person(name string, age int);" + 85 | "CREATE EDGE IF NOT EXISTS like(likeness double);" 86 | 87 | // Execute a query 88 | resp, err := gc.Execute([]byte(createSchema)) 89 | if err != nil { 90 | panic(err) 91 | } 92 | 93 | resultSet, _ := wrapper.GenResultSet(resp, gc.Factory(), types.TimezoneInfo{}) 94 | checkResultSet(createSchema, resultSet) 95 | log.Println(resp) 96 | } 97 | // Drop space 98 | { 99 | query := "DROP SPACE IF EXISTS basic_example_space;" 100 | // Send query 101 | resp, err := gc.Execute([]byte(query)) 102 | if err != nil { 103 | panic(err) 104 | } 105 | 106 | resultSet, _ := wrapper.GenResultSet(resp, gc.Factory(), types.TimezoneInfo{}) 107 | checkResultSet(query, resultSet) 108 | } 109 | } 110 | 111 | func executeWithParamsExample(gc nebula.GraphClient) { 112 | params := make(map[string]interface{}) 113 | params["p1"] = true 114 | params["p2"] = 3 115 | params["p3"] = []interface{}{true, 3} 116 | params["p4"] = map[string]interface{}{"a": true, "b": 3} 117 | 118 | gql := "RETURN abs($p2)+1 AS col1, toBoolean($p1) and false AS col2, $p3, $p4.a" 119 | resp, err := gc.ExecuteWithParameter([]byte(gql), params) 120 | if err != nil { 121 | log.Printf("execute with params failed: %s\n", err.Error()) 122 | return 123 | } 124 | 125 | resultSet, _ := wrapper.GenResultSet(resp, gc.Factory(), types.TimezoneInfo{}) 126 | checkResultSet(gql, resultSet) 127 | // Get all column names from the resultSet 128 | colNames := resultSet.GetColNames() 129 | fmt.Printf("Column names: %s\n", strings.Join(colNames, ", ")) 130 | fmt.Println(resultSet.AsStringTable()) 131 | // Get a row from resultSet 132 | record, err := resultSet.GetRowValuesByIndex(0) 133 | if err != nil { 134 | log.Fatal(err.Error()) 135 | } 136 | // Print whole row 137 | fmt.Printf("The first row elements: %s\n", record.String()) 138 | } 139 | 140 | func factoryExample(c nebula.Client) { 141 | examplef := func(factory nebula.Factory) { 142 | s := []byte{1, 2, 3} 143 | vb := factory.NewValueBuilder() 144 | vb.SVal(s) 145 | v1 := vb.Build() 146 | v2 := vb.Build().SetSVal([]byte{1, 2}) 147 | i1 := v1.Unwrap() 148 | i2 := v2.Unwrap() 149 | log.Printf("\n%v, %v\n%p, %p;\n%v, %v", v1 == v2, i1 == i2, i1, i2, v1.GetSVal(), v2.GetSVal()) 150 | } 151 | 152 | log.Println("get factory by client version:") 153 | factory, _ := nebula.NewFactory(nebula.WithVersion(c.Version())) 154 | examplef(factory) 155 | 156 | log.Println("get factory by graph client version:") 157 | factory, _ = nebula.NewFactory(nebula.WithVersion(c.Graph().Version())) 158 | examplef(factory) 159 | 160 | log.Println("get factory by client:") 161 | examplef(c.Factory()) 162 | 163 | log.Println("get factory by graph client:") 164 | examplef(c.Graph().Factory()) 165 | } 166 | 167 | func checkResultSet(prefix string, res *wrapper.ResultSet) { 168 | if !res.IsSucceed() { 169 | log.Fatal(fmt.Sprintf("%s, ErrorCode: %v, ErrorMsg: %s", prefix, res.GetErrorCode(), res.GetErrorMsg())) 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /ccore/nebula/factory.go: -------------------------------------------------------------------------------- 1 | package nebula 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 7 | ) 8 | 9 | type ( 10 | Factory interface { 11 | NewValueBuilder() types.ValueBuilder 12 | NewDateBuilder() types.DateBuilder 13 | NewTimeBuilder() types.TimeBuilder 14 | NewDateTimeBuilder() types.DateTimeBuilder 15 | NewEdgeBuilder() types.EdgeBuilder 16 | NewNListBuilder() types.NListBuilder 17 | NewNMapBuilder() types.NMapBuilder 18 | } 19 | 20 | defaultFactory struct { 21 | o Options 22 | factory types.FactoryDriver 23 | initDriverOnce sync.Once 24 | } 25 | ) 26 | 27 | func NewFactory(opts ...Option) (Factory, error) { 28 | o := defaultOptions() 29 | for _, opt := range opts { 30 | opt(&o) 31 | } 32 | o.complete() 33 | if err := o.validate(); err != nil { 34 | return nil, err 35 | } 36 | f := &defaultFactory{ 37 | o: o, 38 | factory: newDriverFactory(), 39 | } 40 | 41 | // init driver when create factory 42 | err := f.initDriver() 43 | if err != nil { 44 | return nil, err 45 | } 46 | return f, nil 47 | } 48 | 49 | func (f *defaultFactory) NewValueBuilder() types.ValueBuilder { 50 | return f.factory.NewValueBuilder() 51 | } 52 | 53 | func (f *defaultFactory) NewDateBuilder() types.DateBuilder { 54 | return f.factory.NewDateBuilder() 55 | } 56 | 57 | func (f *defaultFactory) NewTimeBuilder() types.TimeBuilder { 58 | return f.factory.NewTimeBuilder() 59 | } 60 | 61 | func (f *defaultFactory) NewDateTimeBuilder() types.DateTimeBuilder { 62 | return f.factory.NewDateTimeBuilder() 63 | } 64 | 65 | func (f *defaultFactory) NewEdgeBuilder() types.EdgeBuilder { 66 | return f.factory.NewEdgeBuilder() 67 | } 68 | 69 | func (f *defaultFactory) NewNListBuilder() types.NListBuilder { 70 | return f.factory.NewNListBuilder() 71 | } 72 | 73 | func (f *defaultFactory) NewNMapBuilder() types.NMapBuilder { 74 | return f.factory.NewNMapBuilder() 75 | } 76 | 77 | func (f *defaultFactory) initDriver() error { 78 | factory, err := types.GetFactoryDriver(f.o.version) 79 | if err != nil { 80 | return err 81 | } 82 | f.factory = factory 83 | return nil 84 | } 85 | -------------------------------------------------------------------------------- /ccore/nebula/gateway/dao/dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula" 7 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/gateway/pool" 8 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 9 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/wrapper" 10 | ) 11 | 12 | type ExecuteResult struct { 13 | Headers []string `json:"headers"` 14 | Tables []map[string]types.Any `json:"tables"` 15 | TimeCost int64 `json:"timeCost"` 16 | LocalParams types.ParameterMap `json:"localParams"` 17 | } 18 | 19 | type list []types.Any 20 | 21 | func getID(idWarp wrapper.ValueWrapper) types.Any { 22 | idType := idWarp.GetType() 23 | var vid types.Any 24 | if idType == "string" { 25 | vid, _ = idWarp.AsString() 26 | } else if idType == "int" { 27 | vid, _ = idWarp.AsInt() 28 | } 29 | return vid 30 | } 31 | 32 | func getValue(valWarp *wrapper.ValueWrapper) (types.Any, error) { 33 | switch valWarp.GetType() { 34 | case "vertex", "edge", "path", "list", "map", "set": 35 | return valWarp.String(), nil 36 | default: 37 | return getBasicValue(valWarp) 38 | } 39 | } 40 | 41 | func getBasicValue(valWarp *wrapper.ValueWrapper) (types.Any, error) { 42 | var valType = valWarp.GetType() 43 | if valType == "null" { 44 | value, err := valWarp.AsNull() 45 | switch value { 46 | case types.NullType___NULL__: 47 | return "NULL", err 48 | case types.NullType_NaN: 49 | return "NaN", err 50 | case types.NullType_BAD_DATA: 51 | return "BAD_DATA", err 52 | case types.NullType_BAD_TYPE: 53 | return "BAD_TYPE", err 54 | case types.NullType_OUT_OF_RANGE: 55 | return "OUT_OF_RANGE", err 56 | case types.NullType_DIV_BY_ZERO: 57 | return "DIV_BY_ZERO", err 58 | case types.NullType_UNKNOWN_PROP: 59 | return "UNKNOWN_PROP", err 60 | case types.NullType_ERR_OVERFLOW: 61 | return "ERR_OVERFLOW", err 62 | } 63 | return "NULL", err 64 | } else if valType == "bool" { 65 | return valWarp.AsBool() 66 | } else if valType == "int" { 67 | return valWarp.AsInt() 68 | } else if valType == "float" { 69 | return valWarp.AsFloat() 70 | } else if valType == "string" { 71 | return valWarp.AsString() 72 | } else if valType == "date" { 73 | return valWarp.String(), nil 74 | } else if valType == "time" { 75 | return valWarp.String(), nil 76 | } else if valType == "datetime" { 77 | return valWarp.String(), nil 78 | } else if valType == "geography" { 79 | return valWarp.String(), nil 80 | } else if valType == "duration" { 81 | return valWarp.String(), nil 82 | } else if valType == "empty" { 83 | return "_EMPTY_", nil 84 | } 85 | return "", nil 86 | } 87 | 88 | func getVertexInfo(valWarp *wrapper.ValueWrapper, data map[string]types.Any) (map[string]types.Any, error) { 89 | node, err := valWarp.AsNode() 90 | if err != nil { 91 | return nil, err 92 | } 93 | id := node.GetID() 94 | data["vid"] = getID(id) 95 | tags := make([]string, 0) 96 | properties := make(map[string]map[string]types.Any) 97 | for _, tagName := range node.GetTags() { 98 | tags = append(tags, tagName) 99 | props, err := node.Properties(tagName) 100 | if err != nil { 101 | return nil, err 102 | } 103 | _props := make(map[string]types.Any) 104 | for k, v := range props { 105 | value, err := getValue(v) 106 | if err != nil { 107 | return nil, err 108 | } 109 | _props[k] = value 110 | } 111 | properties[tagName] = _props 112 | } 113 | data["tags"] = tags 114 | data["properties"] = properties 115 | return data, nil 116 | } 117 | 118 | func getEdgeInfo(valWarp *wrapper.ValueWrapper, data map[string]types.Any) (map[string]types.Any, error) { 119 | relationship, err := valWarp.AsRelationship() 120 | if err != nil { 121 | return nil, err 122 | } 123 | srcID := relationship.GetSrcVertexID() 124 | data["srcID"] = getID(srcID) 125 | dstID := relationship.GetDstVertexID() 126 | data["dstID"] = getID(dstID) 127 | edgeName := relationship.GetEdgeName() 128 | data["edgeName"] = edgeName 129 | rank := relationship.GetRanking() 130 | data["rank"] = rank 131 | properties := make(map[string]types.Any) 132 | props := relationship.Properties() 133 | for k, v := range props { 134 | value, err := getValue(v) 135 | if err != nil { 136 | return nil, err 137 | } 138 | properties[k] = value 139 | } 140 | data["properties"] = properties 141 | return data, nil 142 | } 143 | 144 | func getPathInfo(valWarp *wrapper.ValueWrapper, data map[string]types.Any) (map[string]types.Any, error) { 145 | path, err := valWarp.AsPath() 146 | if err != nil { 147 | return nil, err 148 | } 149 | relationships := path.GetRelationships() 150 | var _relationships []types.Any 151 | for _, relation := range relationships { 152 | _relation := make(map[string]types.Any) 153 | srcID := relation.GetSrcVertexID() 154 | _relation["srcID"] = getID(srcID) 155 | dstID := relation.GetDstVertexID() 156 | _relation["dstID"] = getID(dstID) 157 | edgeName := relation.GetEdgeName() 158 | _relation["edgeName"] = edgeName 159 | rank := relation.GetRanking() 160 | _relation["rank"] = rank 161 | _relationships = append(_relationships, _relation) 162 | } 163 | data["relationships"] = _relationships 164 | if len(relationships) == 0 { 165 | nodes := path.GetNodes() 166 | if len(nodes) > 0 { 167 | startNode := nodes[0] 168 | data["srcID"] = getID(startNode.GetID()) 169 | } 170 | } 171 | return data, nil 172 | } 173 | 174 | func getListInfo(valWarp *wrapper.ValueWrapper, listType string, _verticesParsedList *list, _edgesParsedList *list, _pathsParsedList *list) error { 175 | var valueList []wrapper.ValueWrapper 176 | var err error 177 | if listType == "list" { 178 | valueList, err = valWarp.AsList() 179 | } else if listType == "set" { 180 | valueList, err = valWarp.AsDedupList() 181 | } 182 | if err != nil { 183 | return err 184 | } 185 | for _, v := range valueList { 186 | var props = make(map[string]types.Any) 187 | vType := v.GetType() 188 | props["type"] = vType 189 | if vType == "vertex" { 190 | props, err = getVertexInfo(&v, props) 191 | if err == nil { 192 | *_verticesParsedList = append(*_verticesParsedList, props) 193 | } else { 194 | return err 195 | } 196 | } else if vType == "edge" { 197 | props, err = getEdgeInfo(&v, props) 198 | if err == nil { 199 | *_edgesParsedList = append(*_edgesParsedList, props) 200 | } else { 201 | return err 202 | } 203 | } else if vType == "path" { 204 | props, err = getPathInfo(&v, props) 205 | if err == nil { 206 | *_pathsParsedList = append(*_pathsParsedList, props) 207 | } else { 208 | return err 209 | } 210 | } else if vType == "list" { 211 | err = getListInfo(&v, "list", _verticesParsedList, _edgesParsedList, _pathsParsedList) 212 | if err != nil { 213 | return err 214 | } 215 | } else if vType == "map" { 216 | err = getMapInfo(&v, _verticesParsedList, _edgesParsedList, _pathsParsedList) 217 | if err != nil { 218 | return err 219 | } 220 | } else if vType == "set" { 221 | err = getListInfo(&v, "set", _verticesParsedList, _edgesParsedList, _pathsParsedList) 222 | if err != nil { 223 | return err 224 | } 225 | } else { 226 | // no need to parse basic value now 227 | } 228 | } 229 | return nil 230 | } 231 | 232 | func getMapInfo(valWarp *wrapper.ValueWrapper, _verticesParsedList *list, _edgesParsedList *list, _pathsParsedList *list) error { 233 | valueMap, err := valWarp.AsMap() 234 | if err != nil { 235 | return err 236 | } 237 | for _, v := range valueMap { 238 | vType := v.GetType() 239 | if vType == "vertex" { 240 | _props := make(map[string]types.Any) 241 | _props, err = getVertexInfo(&v, _props) 242 | if err == nil { 243 | *_verticesParsedList = append(*_verticesParsedList, _props) 244 | } else { 245 | return err 246 | } 247 | } else if vType == "edge" { 248 | _props := make(map[string]types.Any) 249 | _props, err = getEdgeInfo(&v, _props) 250 | if err == nil { 251 | *_edgesParsedList = append(*_edgesParsedList, _props) 252 | } else { 253 | return err 254 | } 255 | } else if vType == "path" { 256 | _props := make(map[string]types.Any) 257 | _props, err = getPathInfo(&v, _props) 258 | if err == nil { 259 | *_pathsParsedList = append(*_pathsParsedList, _props) 260 | } else { 261 | return err 262 | } 263 | } else if vType == "list" { 264 | err = getListInfo(&v, "list", _verticesParsedList, _edgesParsedList, _pathsParsedList) 265 | if err != nil { 266 | return err 267 | } 268 | } else if vType == "map" { 269 | err = getMapInfo(&v, _verticesParsedList, _edgesParsedList, _pathsParsedList) 270 | if err != nil { 271 | return err 272 | } 273 | } else if vType == "set" { 274 | err = getListInfo(&v, "set", _verticesParsedList, _edgesParsedList, _pathsParsedList) 275 | if err != nil { 276 | return err 277 | } 278 | } else { 279 | // no need to parse basic value now 280 | } 281 | } 282 | return nil 283 | } 284 | 285 | // Connect return if the nebula connect succeed 286 | func Connect(address string, port int, username string, password string, opts ...nebula.Option) (*pool.ClientInfo, error) { 287 | info, err := pool.NewClient(address, port, username, password, opts...) 288 | if err != nil { 289 | return nil, err 290 | } 291 | return info, nil 292 | } 293 | 294 | func Disconnect(nsid string) error { 295 | client, err := pool.GetClient(nsid) 296 | if err != nil { 297 | return err 298 | } 299 | client.CloseChannel <- true 300 | 301 | return nil 302 | } 303 | 304 | /* 305 | executes the gql based on nsid, 306 | and returns result, the runtime panic error and the result error. 307 | */ 308 | func Execute(nsid string, gql string, paramList types.ParameterList) (ExecuteResult, interface{}, error) { 309 | result := ExecuteResult{ 310 | Headers: make([]string, 0), 311 | Tables: make([]map[string]types.Any, 0), 312 | LocalParams: nil, 313 | } 314 | client, err := pool.GetClient(nsid) 315 | if err != nil { 316 | return result, nil, err 317 | } 318 | responseChannel := make(chan pool.ChannelResponse) 319 | client.RequestChannel <- pool.ChannelRequest{ 320 | Gql: gql, 321 | ResponseChannel: responseChannel, 322 | ParamList: paramList, 323 | } 324 | response := <-responseChannel 325 | paramsMap := response.Params 326 | if len(paramsMap) > 0 { 327 | result.LocalParams = paramsMap 328 | } 329 | if response.Error != nil { 330 | return result, response.Msg, response.Error 331 | } 332 | res := response.Result 333 | if response.Result == nil { 334 | return result, nil, nil 335 | } 336 | if res.IsSetPlanDesc() { 337 | resp := response.Result 338 | if response.Result == nil { 339 | return result, nil, nil 340 | } 341 | format := string(resp.GetPlanDesc().GetFormat()) 342 | if format == "row" { 343 | result.Headers = []string{"id", "name", "dependencies", "profiling data", "operator info"} 344 | rows := res.MakePlanByRow() 345 | for i := 0; i < len(rows); i++ { 346 | var rowValue = make(map[string]types.Any) 347 | rowValue["id"] = rows[i][0] 348 | rowValue["name"] = rows[i][1] 349 | rowValue["dependencies"] = rows[i][2] 350 | rowValue["profiling data"] = rows[i][3] 351 | rowValue["operator info"] = rows[i][4] 352 | result.Tables = append(result.Tables, rowValue) 353 | } 354 | return result, nil, err 355 | } else { 356 | var rowValue = make(map[string]types.Any) 357 | result.Headers = append(result.Headers, "format") 358 | if format == "dot" { 359 | rowValue["format"] = res.MakeDotGraph() 360 | } else if format == "dot:struct" { 361 | rowValue["format"] = res.MakeDotGraphByStruct() 362 | } 363 | result.Tables = append(result.Tables, rowValue) 364 | return result, nil, err 365 | } 366 | } 367 | if !res.IsSucceed() { 368 | return result, nil, errors.New(res.GetErrorMsg()) 369 | } 370 | if !res.IsEmpty() { 371 | records, err := res.GetRecords() 372 | if err != nil { 373 | return result, nil, err 374 | } 375 | 376 | rowSize := len(records) 377 | colSize := res.GetColSize() 378 | colNames := res.GetColNames() 379 | result.Headers = colNames 380 | 381 | for i := 0; i < rowSize; i++ { 382 | var rowValue = make(map[string]types.Any) 383 | var _verticesParsedList = make(list, 0) 384 | var _edgesParsedList = make(list, 0) 385 | var _pathsParsedList = make(list, 0) 386 | 387 | for j := 0; j < colSize; j++ { 388 | rowData, err := records[i].GetValueByIndex(j) 389 | if err != nil { 390 | return result, nil, err 391 | } 392 | value, err := getValue(rowData) 393 | if err != nil { 394 | return result, nil, err 395 | } 396 | rowValue[result.Headers[j]] = value 397 | valueType := rowData.GetType() 398 | if valueType == "vertex" { 399 | var parseValue = make(map[string]types.Any) 400 | parseValue, err = getVertexInfo(rowData, parseValue) 401 | parseValue["type"] = "vertex" 402 | _verticesParsedList = append(_verticesParsedList, parseValue) 403 | } else if valueType == "edge" { 404 | var parseValue = make(map[string]types.Any) 405 | parseValue, err = getEdgeInfo(rowData, parseValue) 406 | parseValue["type"] = "edge" 407 | _edgesParsedList = append(_edgesParsedList, parseValue) 408 | } else if valueType == "path" { 409 | var parseValue = make(map[string]types.Any) 410 | parseValue, err = getPathInfo(rowData, parseValue) 411 | parseValue["type"] = "path" 412 | _pathsParsedList = append(_pathsParsedList, parseValue) 413 | } else if valueType == "list" { 414 | err = getListInfo(rowData, "list", &_verticesParsedList, &_edgesParsedList, &_pathsParsedList) 415 | } else if valueType == "set" { 416 | err = getListInfo(rowData, "set", &_verticesParsedList, &_edgesParsedList, &_pathsParsedList) 417 | } else if valueType == "map" { 418 | err = getMapInfo(rowData, &_verticesParsedList, &_edgesParsedList, &_pathsParsedList) 419 | } 420 | if len(_verticesParsedList) > 0 { 421 | rowValue["_verticesParsedList"] = _verticesParsedList 422 | } 423 | if len(_edgesParsedList) > 0 { 424 | rowValue["_edgesParsedList"] = _edgesParsedList 425 | } 426 | if len(_pathsParsedList) > 0 { 427 | rowValue["_pathsParsedList"] = _pathsParsedList 428 | } 429 | if err != nil { 430 | return result, nil, err 431 | } 432 | } 433 | result.Tables = append(result.Tables, rowValue) 434 | } 435 | } 436 | result.TimeCost = res.GetLatency() 437 | return result, nil, nil 438 | } 439 | -------------------------------------------------------------------------------- /ccore/nebula/gateway/examples/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/gateway/dao" 7 | ) 8 | 9 | func main() { 10 | var ( 11 | address = "192.168.8.167" 12 | port = 9669 13 | username = "root" 14 | password = "123" 15 | ) 16 | 17 | info, err := dao.Connect(address, port, username, password) 18 | if err != nil { 19 | log.Println("error: ", err) 20 | } 21 | nsid := info.ClientID 22 | log.Println(*info) 23 | defer dao.Disconnect(nsid) 24 | 25 | gql := "CREATE SPACE IF NOT EXISTS basic_example_space(vid_type=FIXED_STRING(20)); " + 26 | "USE basic_example_space;" + 27 | "CREATE TAG IF NOT EXISTS person(name string, age int);" + 28 | "CREATE EDGE IF NOT EXISTS like(likeness double);" 29 | res, p, err := dao.Execute(nsid, gql, nil) 30 | if err != nil { 31 | log.Println("error: ", err) 32 | if p != nil { 33 | log.Fatal(p) 34 | } 35 | } 36 | 37 | log.Println(res) 38 | 39 | gql = "DROP SPACE IF EXISTS basic_example_space;" 40 | res, p, err = dao.Execute(nsid, gql, nil) 41 | if err != nil { 42 | log.Println("error: ", err) 43 | if p != nil { 44 | log.Fatal(p) 45 | } 46 | } 47 | 48 | log.Println(res) 49 | } 50 | -------------------------------------------------------------------------------- /ccore/nebula/gateway/pool/pool.go: -------------------------------------------------------------------------------- 1 | package pool 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | "regexp" 8 | "strconv" 9 | "strings" 10 | "sync" 11 | "time" 12 | 13 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 14 | uuid "github.com/satori/go.uuid" 15 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula" 16 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 17 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/wrapper" 18 | ) 19 | 20 | var ( 21 | ConnectionClosedError = errors.New("an existing connection was forcibly closed, please check your network") 22 | SessionLostError = errors.New("the connection session was lost, please connect again") 23 | InterruptError = errors.New("other statements was not executed due to this error") 24 | ) 25 | 26 | // Console side commands 27 | const ( 28 | Unknown = -1 29 | Param = 1 30 | Params = 2 31 | clientRecycleNum = 30 32 | clientMaxNum = 200 33 | SessionExpiredDuration int64 = 3600 34 | ) 35 | 36 | type Account struct { 37 | username string 38 | password string 39 | } 40 | 41 | type ChannelResponse struct { 42 | Result *wrapper.ResultSet 43 | Params types.ParameterMap 44 | Msg interface{} 45 | Error error 46 | } 47 | 48 | type ChannelRequest struct { 49 | Gql string 50 | ResponseChannel chan ChannelResponse 51 | ParamList types.ParameterList 52 | } 53 | 54 | type Client struct { 55 | graphClient nebula.GraphClient 56 | RequestChannel chan ChannelRequest 57 | CloseChannel chan bool 58 | updateTime int64 59 | parameterMap types.ParameterMap 60 | account *Account 61 | timezone types.TimezoneInfo 62 | } 63 | 64 | type ClientInfo struct { 65 | ClientID string 66 | NebulaVersion nebula.Version 67 | } 68 | 69 | var ( 70 | clientPool = make(map[string]*Client) 71 | currentClientNum = 0 72 | clientMux sync.Mutex 73 | 74 | ClientNotExistedError = errors.New("get client error: client not existed, session expired") 75 | ) 76 | 77 | func isThriftProtoError(err error) bool { 78 | protoErr, ok := err.(thrift.ProtocolException) 79 | if !ok { 80 | return false 81 | } 82 | if protoErr.TypeID() != thrift.UNKNOWN_PROTOCOL_EXCEPTION { 83 | return false 84 | } 85 | errPrefix := []string{"wsasend", "wsarecv", "write:"} 86 | errStr := protoErr.Error() 87 | for _, e := range errPrefix { 88 | if strings.Contains(errStr, e) { 89 | return true 90 | } 91 | } 92 | return false 93 | } 94 | 95 | func isThriftTransportError(err error) bool { 96 | if transErr, ok := err.(thrift.TransportException); ok { 97 | typeId := transErr.TypeID() 98 | if typeId == thrift.UNKNOWN_TRANSPORT_EXCEPTION || typeId == thrift.TIMED_OUT { 99 | if strings.Contains(transErr.Error(), "read:") { 100 | return true 101 | } 102 | } 103 | } 104 | return false 105 | } 106 | 107 | func isCmd(query string) (isLocal bool, localCmd int, args []string) { 108 | isLocal = false 109 | localCmd = Unknown 110 | plain := strings.TrimSpace(query) 111 | if len(plain) < 1 || plain[0] != ':' { 112 | return 113 | } 114 | isLocal = true 115 | words := strings.Fields(plain[1:]) 116 | localCmdName := words[0] 117 | switch strings.ToLower(localCmdName) { 118 | case "param": 119 | localCmd = Param 120 | args = []string{plain} 121 | case "params": 122 | localCmd = Params 123 | args = []string{plain} 124 | } 125 | return 126 | } 127 | 128 | func executeCmd(parameterList types.ParameterList, parameterMap types.ParameterMap) (showMap types.ParameterMap, err error) { 129 | tempMap := make(types.ParameterMap) 130 | for _, v := range parameterList { 131 | // convert interface{} to nebula.Value 132 | if isLocal, cmd, args := isCmd(v); isLocal { 133 | switch cmd { 134 | case Param: 135 | if len(args) == 1 { 136 | err = defineParams(args[0], parameterMap) 137 | } 138 | if err != nil { 139 | return nil, err 140 | } 141 | case Params: 142 | if len(args) == 1 { 143 | err = ListParams(args[0], tempMap, parameterMap) 144 | } 145 | if err != nil { 146 | return nil, err 147 | } 148 | } 149 | } 150 | } 151 | return tempMap, nil 152 | } 153 | 154 | func defineParams(args string, parameterMap types.ParameterMap) (err error) { 155 | argsRewritten := strings.Replace(args, "'", "\"", -1) 156 | reg := regexp.MustCompile(`(?i)^\s*:param\s+(\S+)\s*=>(.*)$`) 157 | matchResult := reg.FindAllStringSubmatch(argsRewritten, -1) 158 | if len(matchResult) != 1 || len(matchResult[0]) != 3 { 159 | err = errors.New("Set params failed. Wrong local command format (" + reg.String() + ") ") 160 | return 161 | } 162 | /* 163 | * :param p1=> -> [":param p1=>",":p1",""] 164 | * :param p2=>3 -> [":param p2=>3",":p2","3"] 165 | */ 166 | paramKey := matchResult[0][1] 167 | paramValue := matchResult[0][2] 168 | if len(paramValue) == 0 { 169 | delete(parameterMap, paramKey) 170 | } else { 171 | paramsWithGoType := make(types.ParameterMap) 172 | param := "{\"" + paramKey + "\"" + ":" + paramValue + "}" 173 | err = json.Unmarshal([]byte(param), ¶msWithGoType) 174 | if err != nil { 175 | return 176 | } 177 | for k, v := range paramsWithGoType { 178 | parameterMap[k] = v 179 | } 180 | } 181 | return nil 182 | } 183 | 184 | func ListParams(args string, tmpParameter types.ParameterMap, sessionMap types.ParameterMap) (err error) { 185 | reg := regexp.MustCompile(`(?i)^\s*:params\s*(\S*)\s*$`) 186 | matchResult := reg.FindAllStringSubmatch(args, -1) 187 | if len(matchResult) != 1 { 188 | err = errors.New("Set params failed. Wrong local command format " + reg.String() + ") ") 189 | return 190 | } 191 | res := matchResult[0] 192 | /* 193 | * :params -> [":params",""] 194 | * :params p1 -> ["params","p1"] 195 | */ 196 | if len(res) != 2 { 197 | return 198 | } 199 | paramKey := matchResult[0][1] 200 | if len(paramKey) == 0 { 201 | for k, v := range sessionMap { 202 | tmpParameter[k] = v 203 | } 204 | } else { 205 | if paramValue, ok := sessionMap[paramKey]; ok { 206 | tmpParameter[paramKey] = paramValue 207 | } else { 208 | err = errors.New("Unknown parameter: " + paramKey) 209 | } 210 | } 211 | return nil 212 | } 213 | 214 | func NewClient(address string, port int, username string, password string, opts ...nebula.Option) (*ClientInfo, error) { 215 | var err error 216 | 217 | // TODO: it's better to add a schedule to make it instead 218 | if currentClientNum > clientRecycleNum { 219 | go recycleClients() 220 | if currentClientNum >= clientMaxNum { 221 | return nil, errors.New("There is no idle connection now, please try it later") 222 | } 223 | } 224 | 225 | host := strings.Join([]string{address, strconv.Itoa(port)}, ":") 226 | c, err := nebula.NewGraphClient([]string{host}, username, password, opts...) 227 | if err != nil { 228 | return nil, err 229 | } 230 | if err := c.Open(); err != nil { 231 | return nil, err 232 | } 233 | 234 | u, err := uuid.NewV4() 235 | if err != nil { 236 | return nil, err 237 | } 238 | 239 | nsid := u.String() 240 | ver := c.Version() 241 | 242 | client := &Client{ 243 | graphClient: c, 244 | RequestChannel: make(chan ChannelRequest), 245 | CloseChannel: make(chan bool), 246 | updateTime: time.Now().Unix(), 247 | parameterMap: make(types.ParameterMap), 248 | account: &Account{ 249 | username: username, 250 | password: password, 251 | }, 252 | timezone: c.GetTimezoneInfo(), 253 | } 254 | 255 | clientMux.Lock() 256 | clientPool[nsid] = client 257 | currentClientNum++ 258 | clientMux.Unlock() 259 | 260 | // Make a goroutine to deal with concurrent requests from each connection 261 | go handleRequest(nsid) 262 | 263 | info := &ClientInfo{ 264 | ClientID: nsid, 265 | NebulaVersion: ver, 266 | } 267 | return info, err 268 | } 269 | 270 | func ClearClients() { 271 | for _, client := range clientPool { 272 | client.graphClient.Close() 273 | } 274 | } 275 | 276 | func recycleClients() { 277 | clientMux.Lock() 278 | for _, client := range clientPool { 279 | now := time.Now().Unix() 280 | expireAt := client.updateTime + SessionExpiredDuration 281 | if now > expireAt { 282 | client.CloseChannel <- true 283 | } 284 | } 285 | clientMux.Unlock() 286 | } 287 | 288 | func handleRequest(nsid string) { 289 | var err error 290 | client := clientPool[nsid] 291 | for { 292 | select { 293 | case request := <-client.RequestChannel: 294 | func() { 295 | defer func() { 296 | if err := recover(); err != nil { 297 | request.ResponseChannel <- ChannelResponse{ 298 | Result: nil, 299 | Msg: err, 300 | Error: SessionLostError, 301 | } 302 | } 303 | }() 304 | showMap := make(types.ParameterMap) 305 | if request.ParamList != nil && len(request.ParamList) > 0 { 306 | showMap, err = executeCmd(request.ParamList, client.parameterMap) 307 | if err != nil { 308 | if len(request.Gql) > 0 { 309 | err = fmt.Errorf("%s. %s.\n", err.Error(), InterruptError.Error()) 310 | } 311 | request.ResponseChannel <- ChannelResponse{ 312 | Result: nil, 313 | Params: showMap, 314 | Error: err, 315 | } 316 | return 317 | } 318 | } 319 | 320 | if len(request.Gql) > 0 { 321 | execResponse, err := client.graphClient.ExecuteWithParameter([]byte(request.Gql), client.parameterMap) 322 | if err != nil { 323 | if isThriftProtoError(err) || isThriftTransportError(err) { 324 | err = ConnectionClosedError 325 | } 326 | request.ResponseChannel <- ChannelResponse{ 327 | Result: nil, 328 | Error: err, 329 | } 330 | return 331 | } 332 | 333 | res, err := wrapper.GenResultSet(execResponse, client.graphClient.Factory(), client.timezone) 334 | if err != nil { 335 | err = fmt.Errorf("%s. %s.\n", err.Error(), InterruptError.Error()) 336 | } 337 | request.ResponseChannel <- ChannelResponse{ 338 | Result: res, 339 | Params: showMap, 340 | Error: err, 341 | } 342 | } else { 343 | request.ResponseChannel <- ChannelResponse{ 344 | Result: nil, 345 | Params: showMap, 346 | Error: nil, 347 | } 348 | } 349 | }() 350 | case <-client.CloseChannel: 351 | clientMux.Lock() 352 | _ = client.graphClient.Close() 353 | currentClientNum-- 354 | delete(clientPool, nsid) 355 | clientMux.Unlock() 356 | return // Exit loop 357 | } 358 | } 359 | } 360 | 361 | func GetClient(nsid string) (*Client, error) { 362 | clientMux.Lock() 363 | defer clientMux.Unlock() 364 | 365 | if client, ok := clientPool[nsid]; ok { 366 | client.updateTime = time.Now().Unix() 367 | return client, nil 368 | } 369 | 370 | return nil, ClientNotExistedError 371 | } 372 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v2_5/driver.go: -------------------------------------------------------------------------------- 1 | package v2_5 2 | 3 | import ( 4 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 5 | 6 | nthrift "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_5" 7 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 8 | ) 9 | 10 | var ( 11 | _ types.Driver = (*defaultDriver)(nil) 12 | _ types.FactoryDriver = (*defaultFactoryDriver)(nil) 13 | ) 14 | 15 | type ( 16 | defaultDriver struct{} 17 | defaultFactoryDriver struct{} 18 | ) 19 | 20 | func init() { 21 | types.Register(types.Version2_5, &defaultDriver{}, &defaultFactoryDriver{}) 22 | } 23 | 24 | func (d *defaultDriver) NewGraphClientDriver(transport thrift.Transport, pf thrift.ProtocolFactory) types.GraphClientDriver { 25 | return newGraphClient(transport, pf) 26 | } 27 | 28 | func (d *defaultDriver) NewMetaClientDriver(transport thrift.Transport, pf thrift.ProtocolFactory) types.MetaClientDriver { 29 | return newMetaClient(transport, pf) 30 | } 31 | 32 | func (d *defaultDriver) NewStorageClientDriver(transport thrift.Transport, pf thrift.ProtocolFactory) types.StorageAdminClientDriver { 33 | return newStorageAdminClient(transport, pf) 34 | } 35 | 36 | func (f *defaultFactoryDriver) NewValueBuilder() types.ValueBuilder { 37 | value := nthrift.NewValue() 38 | return &valueBuilder{value} 39 | } 40 | 41 | func (f *defaultFactoryDriver) NewDateBuilder() types.DateBuilder { 42 | date := nthrift.NewDate() 43 | return &dateBuilder{date} 44 | } 45 | 46 | func (f *defaultFactoryDriver) NewTimeBuilder() types.TimeBuilder { 47 | time := nthrift.NewTime() 48 | return &timeBuilder{time} 49 | } 50 | 51 | func (f *defaultFactoryDriver) NewDateTimeBuilder() types.DateTimeBuilder { 52 | dateTime := nthrift.NewDateTime() 53 | return &dateTimeBuilder{dateTime} 54 | } 55 | 56 | func (f *defaultFactoryDriver) NewEdgeBuilder() types.EdgeBuilder { 57 | edge := nthrift.NewEdge() 58 | return &edgeBuilder{edge} 59 | } 60 | 61 | func (f *defaultFactoryDriver) NewNListBuilder() types.NListBuilder { 62 | nlist := nthrift.NewNList() 63 | return &nListBuilder{nlist} 64 | } 65 | 66 | func (f *defaultFactoryDriver) NewNMapBuilder() types.NMapBuilder { 67 | nmap := nthrift.NewNMap() 68 | return &nMapBuilder{nmap} 69 | } 70 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v2_5/error_code.go: -------------------------------------------------------------------------------- 1 | package v2_5 2 | 3 | import ( 4 | nerrors "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/errors" 5 | nthrift "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_5" 6 | ) 7 | 8 | func codeErrorIfHappened(code nthrift.ErrorCode, msg []byte) error { 9 | if code == nthrift.ErrorCode_SUCCEEDED { 10 | return nil 11 | } 12 | // TODO: Align with the code of nerrors 13 | return nerrors.NewCodeError(nerrors.ErrorCode(code), string(msg)) 14 | } 15 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v2_5/graph.go: -------------------------------------------------------------------------------- 1 | package v2_5 2 | 3 | import ( 4 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 5 | nerrors "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/errors" 6 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_5/graph" 7 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 8 | ) 9 | 10 | var ( 11 | _ types.GraphClientDriver = (*defaultGraphClient)(nil) 12 | ) 13 | 14 | type ( 15 | defaultGraphClient struct { 16 | graph *graph.GraphServiceClient 17 | } 18 | ) 19 | 20 | func newGraphClient(transport thrift.Transport, pf thrift.ProtocolFactory) types.GraphClientDriver { 21 | return &defaultGraphClient{ 22 | graph: graph.NewGraphServiceClientFactory(transport, pf), 23 | } 24 | } 25 | 26 | func (c *defaultGraphClient) VerifyClientVersion() error { 27 | // v2.5 is not support verify client version, and it's the lowest version, so return not error. 28 | return nil 29 | } 30 | 31 | func (c *defaultGraphClient) Open() error { 32 | return c.graph.Open() 33 | } 34 | 35 | func (c *defaultGraphClient) Authenticate(username, password string) (types.AuthResponse, error) { 36 | resp, err := c.graph.Authenticate([]byte(username), []byte(password)) 37 | if err != nil { 38 | return nil, err 39 | } 40 | if err = codeErrorIfHappened(resp.ErrorCode, resp.ErrorMsg); err != nil { 41 | return nil, err 42 | } 43 | return newAuthResponseWrapper(resp), nil 44 | } 45 | 46 | func (c *defaultGraphClient) Signout(sessionId int64) (err error) { 47 | return c.graph.Signout(sessionId) 48 | } 49 | 50 | func (c *defaultGraphClient) Execute(sessionId int64, stmt []byte) (types.ExecutionResponse, error) { 51 | resp, err := c.graph.Execute(sessionId, stmt) 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | if err = codeErrorIfHappened(resp.ErrorCode, resp.ErrorMsg); err != nil { 57 | return nil, err 58 | } 59 | return newExecutionResponseWrapper(resp), nil 60 | } 61 | 62 | func (c *defaultGraphClient) ExecuteJson(sessionId int64, stmt []byte) ([]byte, error) { 63 | return c.graph.ExecuteJson(sessionId, stmt) 64 | } 65 | 66 | func (c *defaultGraphClient) ExecuteWithParameter(sessionId int64, stmt []byte, params map[string]types.Value) (types.ExecutionResponse, error) { 67 | return nil, nerrors.ErrUnsupported 68 | } 69 | 70 | func (c *defaultGraphClient) Close() error { 71 | if c.graph != nil { 72 | if err := c.graph.Close(); err != nil { 73 | return err 74 | } 75 | } 76 | return nil 77 | } 78 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v2_5/meta.go: -------------------------------------------------------------------------------- 1 | package v2_5 2 | 3 | import ( 4 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 5 | 6 | nerrors "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/errors" 7 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_5/meta" 8 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 9 | ) 10 | 11 | var ( 12 | _ types.MetaClientDriver = (*defaultMetaClient)(nil) 13 | ) 14 | 15 | type ( 16 | defaultMetaClient struct { 17 | meta *meta.MetaServiceClient 18 | } 19 | ) 20 | 21 | func newMetaClient(transport thrift.Transport, pf thrift.ProtocolFactory) types.MetaClientDriver { 22 | return &defaultMetaClient{ 23 | meta: meta.NewMetaServiceClientFactory(transport, pf), 24 | } 25 | } 26 | 27 | func (c *defaultMetaClient) Open() error { 28 | return c.meta.Open() 29 | } 30 | 31 | func (c *defaultMetaClient) VerifyClientVersion() error { 32 | // v2.5 is not support verify client version, and it's the lowest version, so return not error. 33 | return nil 34 | } 35 | 36 | func (c *defaultMetaClient) Close() error { 37 | if c.meta != nil { 38 | if err := c.meta.Close(); err != nil { 39 | return err 40 | } 41 | } 42 | return nil 43 | } 44 | 45 | func (c *defaultMetaClient) AddHosts(endpoints []string) (types.MetaBaser, error) { 46 | return nil, nerrors.ErrUnsupported 47 | } 48 | 49 | func (c *defaultMetaClient) AddHostsIntoZone(zone string, endpoints []string, isNew bool) (types.MetaBaser, error) { 50 | return nil, nerrors.ErrUnsupported 51 | } 52 | 53 | func (c *defaultMetaClient) DropHosts(endpoints []string) (types.MetaBaser, error) { 54 | return nil, nerrors.ErrUnsupported 55 | } 56 | 57 | func (c *defaultMetaClient) ListSpaces() (types.Spaces, error) { 58 | req := meta.NewListSpacesReq() 59 | 60 | resp, err := c.meta.ListSpaces(req) 61 | if err != nil { 62 | return nil, err 63 | } 64 | 65 | if err := codeErrorIfHappened(resp.Code, nil); err != nil { 66 | return nil, err 67 | } 68 | 69 | return newSpacesWrapper(resp), nil 70 | } 71 | 72 | func (c *defaultMetaClient) Balance(req types.BalanceReq) (types.Balancer, error) { 73 | // TODO: add 2.5 Balance logic 74 | return nil, nerrors.ErrUnsupported 75 | } 76 | 77 | func (c *defaultMetaClient) ListHosts() (types.Hosts, error) { 78 | req := meta.NewListHostsReq() 79 | 80 | resp, err := c.meta.ListHosts(req) 81 | if err != nil { 82 | return nil, err 83 | } 84 | 85 | return newHostsWrapper(resp), nil 86 | } 87 | 88 | func (c *defaultMetaClient) ListZones() (types.Zones, error) { 89 | return nil, nerrors.ErrUnsupported 90 | } 91 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v2_5/storage_admin.go: -------------------------------------------------------------------------------- 1 | package v2_5 2 | 3 | import ( 4 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 5 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_5/storage" 6 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 7 | ) 8 | 9 | var ( 10 | _ types.StorageAdminClientDriver = (*defaultStorageAdminClient)(nil) 11 | ) 12 | 13 | type ( 14 | defaultStorageAdminClient struct { 15 | storageAdmin *storage.StorageAdminServiceClient 16 | } 17 | ) 18 | 19 | func newStorageAdminClient(transport thrift.Transport, pf thrift.ProtocolFactory) types.StorageAdminClientDriver { 20 | return &defaultStorageAdminClient{ 21 | storageAdmin: storage.NewStorageAdminServiceClientFactory(transport, pf), 22 | } 23 | } 24 | 25 | func (c *defaultStorageAdminClient) VerifyClientVersion() error { 26 | // v2.5 is not support verify client version, and it's the lowest version, so return not error. 27 | return nil 28 | } 29 | 30 | func (c *defaultStorageAdminClient) Open() error { 31 | return c.storageAdmin.Open() 32 | } 33 | 34 | func (c *defaultStorageAdminClient) Close() error { 35 | if c.storageAdmin != nil { 36 | if err := c.storageAdmin.Close(); err != nil { 37 | return err 38 | } 39 | } 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v2_6/driver.go: -------------------------------------------------------------------------------- 1 | package v2_6 2 | 3 | import ( 4 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 5 | 6 | nthrift "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_6" 7 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 8 | ) 9 | 10 | var ( 11 | _ types.Driver = (*defaultDriver)(nil) 12 | _ types.FactoryDriver = (*defaultFactoryDriver)(nil) 13 | ) 14 | 15 | type ( 16 | defaultDriver struct{} 17 | defaultFactoryDriver struct{} 18 | ) 19 | 20 | func init() { 21 | types.Register(types.Version2_6, &defaultDriver{}, &defaultFactoryDriver{}) 22 | } 23 | 24 | func (d *defaultDriver) NewGraphClientDriver(transport thrift.Transport, pf thrift.ProtocolFactory) types.GraphClientDriver { 25 | return newGraphClient(transport, pf) 26 | } 27 | 28 | func (d *defaultDriver) NewMetaClientDriver(transport thrift.Transport, pf thrift.ProtocolFactory) types.MetaClientDriver { 29 | return newMetaClient(transport, pf) 30 | } 31 | 32 | func (d *defaultDriver) NewStorageClientDriver(transport thrift.Transport, pf thrift.ProtocolFactory) types.StorageAdminClientDriver { 33 | return newStorageAdminClient(transport, pf) 34 | } 35 | 36 | func (f *defaultFactoryDriver) NewValueBuilder() types.ValueBuilder { 37 | value := nthrift.NewValue() 38 | return &valueBuilder{value} 39 | } 40 | 41 | func (f *defaultFactoryDriver) NewDateBuilder() types.DateBuilder { 42 | date := nthrift.NewDate() 43 | return &dateBuilder{date} 44 | } 45 | 46 | func (f *defaultFactoryDriver) NewTimeBuilder() types.TimeBuilder { 47 | time := nthrift.NewTime() 48 | return &timeBuilder{time} 49 | } 50 | 51 | func (f *defaultFactoryDriver) NewDateTimeBuilder() types.DateTimeBuilder { 52 | dateTime := nthrift.NewDateTime() 53 | return &dateTimeBuilder{dateTime} 54 | } 55 | 56 | func (f *defaultFactoryDriver) NewEdgeBuilder() types.EdgeBuilder { 57 | edge := nthrift.NewEdge() 58 | return &edgeBuilder{edge} 59 | } 60 | 61 | func (f *defaultFactoryDriver) NewNListBuilder() types.NListBuilder { 62 | nlist := nthrift.NewNList() 63 | return &nListBuilder{nlist} 64 | } 65 | 66 | func (f *defaultFactoryDriver) NewNMapBuilder() types.NMapBuilder { 67 | nmap := nthrift.NewNMap() 68 | return &nMapBuilder{nmap} 69 | } 70 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v2_6/error_code.go: -------------------------------------------------------------------------------- 1 | package v2_6 2 | 3 | import ( 4 | nerrors "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/errors" 5 | nthrift "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_6" 6 | ) 7 | 8 | func codeErrorIfHappened(code nthrift.ErrorCode, msg []byte) error { 9 | if code == nthrift.ErrorCode_SUCCEEDED { 10 | return nil 11 | } 12 | // TODO: Align with the code of nerrors 13 | return nerrors.NewCodeError(nerrors.ErrorCode(code), string(msg)) 14 | } 15 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v2_6/graph.go: -------------------------------------------------------------------------------- 1 | package v2_6 2 | 3 | import ( 4 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 5 | nerrors "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/errors" 6 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_6/graph" 7 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 8 | ) 9 | 10 | var ( 11 | _ types.GraphClientDriver = (*defaultGraphClient)(nil) 12 | ) 13 | 14 | type ( 15 | defaultGraphClient struct { 16 | graph *graph.GraphServiceClient 17 | } 18 | ) 19 | 20 | func newGraphClient(transport thrift.Transport, pf thrift.ProtocolFactory) types.GraphClientDriver { 21 | return &defaultGraphClient{ 22 | graph: graph.NewGraphServiceClientFactory(transport, pf), 23 | } 24 | } 25 | 26 | func (c *defaultGraphClient) Open() error { 27 | return c.graph.Open() 28 | } 29 | 30 | func (c *defaultGraphClient) VerifyClientVersion() error { 31 | req := graph.NewVerifyClientVersionReq() 32 | resp, err := c.graph.VerifyClientVersion(req) 33 | if err != nil { 34 | return err 35 | } 36 | return codeErrorIfHappened(resp.ErrorCode, resp.ErrorMsg) 37 | } 38 | 39 | func (c *defaultGraphClient) Authenticate(username, password string) (types.AuthResponse, error) { 40 | resp, err := c.graph.Authenticate([]byte(username), []byte(password)) 41 | if err != nil { 42 | return nil, err 43 | } 44 | 45 | if err = codeErrorIfHappened(resp.ErrorCode, resp.ErrorMsg); err != nil { 46 | return nil, err 47 | } 48 | return newAuthResponseWrapper(resp), nil 49 | } 50 | 51 | func (c *defaultGraphClient) Signout(sessionId int64) (err error) { 52 | return c.graph.Signout(sessionId) 53 | } 54 | 55 | func (c *defaultGraphClient) Execute(sessionId int64, stmt []byte) (types.ExecutionResponse, error) { 56 | resp, err := c.graph.Execute(sessionId, stmt) 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | if err = codeErrorIfHappened(resp.ErrorCode, resp.ErrorMsg); err != nil { 62 | return nil, err 63 | } 64 | return newExecutionResponseWrapper(resp), nil 65 | } 66 | 67 | func (c *defaultGraphClient) ExecuteJson(sessionId int64, stmt []byte) ([]byte, error) { 68 | return c.graph.ExecuteJson(sessionId, stmt) 69 | } 70 | 71 | func (c *defaultGraphClient) ExecuteWithParameter(sessionId int64, stmt []byte, params map[string]types.Value) (types.ExecutionResponse, error) { 72 | return nil, nerrors.ErrUnsupported 73 | } 74 | 75 | func (c *defaultGraphClient) Close() error { 76 | if c.graph != nil { 77 | if err := c.graph.Close(); err != nil { 78 | return err 79 | } 80 | } 81 | return nil 82 | } 83 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v2_6/meta.go: -------------------------------------------------------------------------------- 1 | package v2_6 2 | 3 | import ( 4 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 5 | 6 | nerrors "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/errors" 7 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_6/meta" 8 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 9 | ) 10 | 11 | var ( 12 | _ types.MetaClientDriver = (*defaultMetaClient)(nil) 13 | ) 14 | 15 | type ( 16 | defaultMetaClient struct { 17 | meta *meta.MetaServiceClient 18 | } 19 | ) 20 | 21 | func newMetaClient(transport thrift.Transport, pf thrift.ProtocolFactory) types.MetaClientDriver { 22 | return &defaultMetaClient{ 23 | meta: meta.NewMetaServiceClientFactory(transport, pf), 24 | } 25 | } 26 | 27 | func (c *defaultMetaClient) Open() error { 28 | return c.meta.Open() 29 | } 30 | 31 | func (c *defaultMetaClient) VerifyClientVersion() error { 32 | req := meta.NewVerifyClientVersionReq() 33 | resp, err := c.meta.VerifyClientVersion(req) 34 | if err != nil { 35 | return err 36 | } 37 | return codeErrorIfHappened(resp.Code, resp.ErrorMsg) 38 | } 39 | 40 | func (c *defaultMetaClient) Close() error { 41 | if c.meta != nil { 42 | if err := c.meta.Close(); err != nil { 43 | return err 44 | } 45 | } 46 | return nil 47 | } 48 | 49 | func (c *defaultMetaClient) AddHosts(endpoints []string) (types.MetaBaser, error) { 50 | return nil, nerrors.ErrUnsupported 51 | } 52 | 53 | func (c *defaultMetaClient) AddHostsIntoZone(zone string, endpoints []string, isNew bool) (types.MetaBaser, error) { 54 | return nil, nerrors.ErrUnsupported 55 | } 56 | 57 | func (c *defaultMetaClient) DropHosts(endpoints []string) (types.MetaBaser, error) { 58 | return nil, nerrors.ErrUnsupported 59 | } 60 | 61 | func (c *defaultMetaClient) ListSpaces() (types.Spaces, error) { 62 | req := meta.NewListSpacesReq() 63 | 64 | resp, err := c.meta.ListSpaces(req) 65 | if err != nil { 66 | return nil, err 67 | } 68 | 69 | if err := codeErrorIfHappened(resp.Code, nil); err != nil { 70 | return nil, err 71 | } 72 | 73 | return newSpacesWrapper(resp), nil 74 | } 75 | 76 | func (c *defaultMetaClient) Balance(req types.BalanceReq) (types.Balancer, error) { 77 | // TODO: add 2.6 Balance logic 78 | return nil, nerrors.ErrUnsupported 79 | } 80 | 81 | func (c *defaultMetaClient) ListHosts() (types.Hosts, error) { 82 | req := meta.NewListHostsReq() 83 | 84 | resp, err := c.meta.ListHosts(req) 85 | if err != nil { 86 | return nil, err 87 | } 88 | 89 | return newHostsWrapper(resp), nil 90 | } 91 | 92 | func (c *defaultMetaClient) ListZones() (types.Zones, error) { 93 | return nil, nerrors.ErrUnsupported 94 | } 95 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v2_6/storage_admin.go: -------------------------------------------------------------------------------- 1 | package v2_6 2 | 3 | import ( 4 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 5 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_6/storage" 6 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 7 | ) 8 | 9 | var ( 10 | _ types.StorageAdminClientDriver = (*defaultStorageAdminClient)(nil) 11 | ) 12 | 13 | type ( 14 | defaultStorageAdminClient struct { 15 | storageAdmin *storage.StorageAdminServiceClient 16 | } 17 | ) 18 | 19 | func newStorageAdminClient(transport thrift.Transport, pf thrift.ProtocolFactory) types.StorageAdminClientDriver { 20 | return &defaultStorageAdminClient{ 21 | storageAdmin: storage.NewStorageAdminServiceClientFactory(transport, pf), 22 | } 23 | } 24 | 25 | func (c *defaultStorageAdminClient) Open() error { 26 | return c.storageAdmin.Open() 27 | } 28 | 29 | func (c *defaultStorageAdminClient) Close() error { 30 | if c.storageAdmin != nil { 31 | if err := c.storageAdmin.Close(); err != nil { 32 | return err 33 | } 34 | } 35 | return nil 36 | } 37 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v3_0/driver.go: -------------------------------------------------------------------------------- 1 | package v3_0 2 | 3 | import ( 4 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 5 | 6 | nthrift "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v3_0" 7 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 8 | ) 9 | 10 | var ( 11 | _ types.Driver = (*defaultDriver)(nil) 12 | _ types.FactoryDriver = (*defaultFactoryDriver)(nil) 13 | ) 14 | 15 | type ( 16 | defaultDriver struct{} 17 | defaultFactoryDriver struct{} 18 | ) 19 | 20 | func init() { 21 | types.Register(types.Version3_0, &defaultDriver{}, &defaultFactoryDriver{}) 22 | } 23 | 24 | func (d *defaultDriver) NewGraphClientDriver(transport thrift.Transport, pf thrift.ProtocolFactory) types.GraphClientDriver { 25 | return newGraphClient(transport, pf) 26 | } 27 | 28 | func (d *defaultDriver) NewMetaClientDriver(transport thrift.Transport, pf thrift.ProtocolFactory) types.MetaClientDriver { 29 | return newMetaClient(transport, pf) 30 | } 31 | 32 | func (d *defaultDriver) NewStorageClientDriver(transport thrift.Transport, pf thrift.ProtocolFactory) types.StorageAdminClientDriver { 33 | return newStorageAdminClient(transport, pf) 34 | } 35 | 36 | func (f *defaultFactoryDriver) NewValueBuilder() types.ValueBuilder { 37 | builder := nthrift.NewValueBuilder() 38 | return &valueBuilder{builder} 39 | } 40 | 41 | func (f *defaultFactoryDriver) NewDateBuilder() types.DateBuilder { 42 | builder := nthrift.NewDateBuilder() 43 | return &dateBuilder{builder} 44 | } 45 | 46 | func (f *defaultFactoryDriver) NewTimeBuilder() types.TimeBuilder { 47 | builder := nthrift.NewTimeBuilder() 48 | return &timeBuilder{builder} 49 | } 50 | 51 | func (f *defaultFactoryDriver) NewDateTimeBuilder() types.DateTimeBuilder { 52 | builder := nthrift.NewDateTimeBuilder() 53 | return &dateTimeBuilder{builder} 54 | } 55 | 56 | func (f *defaultFactoryDriver) NewEdgeBuilder() types.EdgeBuilder { 57 | builder := nthrift.NewEdgeBuilder() 58 | return &edgeBuilder{builder} 59 | } 60 | 61 | func (f *defaultFactoryDriver) NewNListBuilder() types.NListBuilder { 62 | builder := nthrift.NewNListBuilder() 63 | return &nListBuilder{builder} 64 | } 65 | 66 | func (f *defaultFactoryDriver) NewNMapBuilder() types.NMapBuilder { 67 | builder := nthrift.NewNMapBuilder() 68 | return &nMapBuilder{builder} 69 | } 70 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v3_0/error_code.go: -------------------------------------------------------------------------------- 1 | package v3_0 2 | 3 | import ( 4 | nerrors "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/errors" 5 | nthrift "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v3_0" 6 | ) 7 | 8 | func codeErrorIfHappened(code nthrift.ErrorCode, msg []byte) error { 9 | if code == nthrift.ErrorCode_SUCCEEDED { 10 | return nil 11 | } 12 | // TODO: Align with the code of nerrors 13 | return nerrors.NewCodeError(nerrors.ErrorCode(code), string(msg)) 14 | } 15 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v3_0/graph.go: -------------------------------------------------------------------------------- 1 | package v3_0 2 | 3 | import ( 4 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 5 | nthrift "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v3_0" 6 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v3_0/graph" 7 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 8 | ) 9 | 10 | var ( 11 | _ types.GraphClientDriver = (*defaultGraphClient)(nil) 12 | ) 13 | 14 | type ( 15 | defaultGraphClient struct { 16 | graph *graph.GraphServiceClient 17 | } 18 | ) 19 | 20 | func newGraphClient(transport thrift.Transport, pf thrift.ProtocolFactory) types.GraphClientDriver { 21 | return &defaultGraphClient{ 22 | graph: graph.NewGraphServiceClientFactory(transport, pf), 23 | } 24 | } 25 | 26 | func (c *defaultGraphClient) Open() error { 27 | return c.graph.Open() 28 | } 29 | 30 | func (c *defaultGraphClient) VerifyClientVersion() error { 31 | req := graph.NewVerifyClientVersionReq() 32 | resp, err := c.graph.VerifyClientVersion(req) 33 | if err != nil { 34 | return err 35 | } 36 | return codeErrorIfHappened(resp.ErrorCode, resp.ErrorMsg) 37 | } 38 | 39 | func (c *defaultGraphClient) Authenticate(username, password string) (types.AuthResponse, error) { 40 | resp, err := c.graph.Authenticate([]byte(username), []byte(password)) 41 | if err != nil { 42 | return nil, err 43 | } 44 | 45 | if err = codeErrorIfHappened(resp.ErrorCode, resp.ErrorMsg); err != nil { 46 | return nil, err 47 | } 48 | return newAuthResponseWrapper(resp), nil 49 | } 50 | 51 | func (c *defaultGraphClient) Signout(sessionId int64) (err error) { 52 | return c.graph.Signout(sessionId) 53 | } 54 | 55 | func (c *defaultGraphClient) Execute(sessionId int64, stmt []byte) (types.ExecutionResponse, error) { 56 | resp, err := c.graph.Execute(sessionId, stmt) 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | if err = codeErrorIfHappened(resp.ErrorCode, resp.ErrorMsg); err != nil { 62 | return nil, err 63 | } 64 | return newExecutionResponseWrapper(resp), nil 65 | } 66 | 67 | func (c *defaultGraphClient) ExecuteJson(sessionId int64, stmt []byte) ([]byte, error) { 68 | return c.graph.ExecuteJson(sessionId, stmt) 69 | } 70 | 71 | func (c *defaultGraphClient) ExecuteWithParameter(sessionId int64, stmt []byte, params map[string]types.Value) (types.ExecutionResponse, error) { 72 | _params := make(map[string]*nthrift.Value, len(params)) 73 | for k, v := range params { 74 | _params[k] = v.Unwrap().(*nthrift.Value) 75 | } 76 | resp, err := c.graph.ExecuteWithParameter(sessionId, stmt, _params) 77 | if err != nil { 78 | return nil, err 79 | } 80 | 81 | if err = codeErrorIfHappened(resp.ErrorCode, resp.ErrorMsg); err != nil { 82 | return nil, err 83 | } 84 | return newExecutionResponseWrapper(resp), nil 85 | } 86 | 87 | func (c *defaultGraphClient) Close() error { 88 | if c.graph != nil { 89 | if err := c.graph.Close(); err != nil { 90 | return err 91 | } 92 | } 93 | return nil 94 | } 95 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v3_0/meta.go: -------------------------------------------------------------------------------- 1 | package v3_0 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "strconv" 7 | 8 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 9 | 10 | nerrors "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/errors" 11 | nthrift "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v3_0" 12 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v3_0/meta" 13 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 14 | ) 15 | 16 | var ( 17 | _ types.MetaClientDriver = (*defaultMetaClient)(nil) 18 | ) 19 | 20 | type ( 21 | defaultMetaClient struct { 22 | meta *meta.MetaServiceClient 23 | } 24 | ) 25 | 26 | func newMetaClient(transport thrift.Transport, pf thrift.ProtocolFactory) types.MetaClientDriver { 27 | return &defaultMetaClient{ 28 | meta: meta.NewMetaServiceClientFactory(transport, pf), 29 | } 30 | } 31 | 32 | func (c *defaultMetaClient) Open() error { 33 | return c.meta.Open() 34 | } 35 | 36 | func (c *defaultMetaClient) VerifyClientVersion() error { 37 | req := meta.NewVerifyClientVersionReq() 38 | resp, err := c.meta.VerifyClientVersion(req) 39 | if err != nil { 40 | return err 41 | } 42 | return codeErrorIfHappened(resp.Code, resp.ErrorMsg) 43 | } 44 | 45 | func (c *defaultMetaClient) Close() error { 46 | if c.meta != nil { 47 | if err := c.meta.Close(); err != nil { 48 | return err 49 | } 50 | } 51 | return nil 52 | } 53 | 54 | func (c *defaultMetaClient) AddHosts(endpoints []string) (types.MetaBaser, error) { 55 | hostsToAdd := make([]*nthrift.HostAddr, 0, len(endpoints)) 56 | for _, ep := range endpoints { 57 | host, portStr, err := net.SplitHostPort(ep) 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | port, err := strconv.Atoi(portStr) 63 | if err != nil { 64 | return nil, err 65 | } 66 | 67 | hostsToAdd = append(hostsToAdd, &nthrift.HostAddr{ 68 | Host: host, 69 | Port: nthrift.Port(port), 70 | }) 71 | } 72 | 73 | req := &meta.AddHostsReq{ 74 | Hosts: hostsToAdd, 75 | } 76 | resp, err := c.meta.AddHosts(req) 77 | if err != nil { 78 | return nil, err 79 | } 80 | 81 | return metaBaserWrap{ 82 | code: nerrors.ErrorCode(resp.GetCode()), 83 | leader: types.HostAddr{ 84 | Host: resp.GetLeader().GetHost(), 85 | Port: resp.GetLeader().GetPort(), 86 | }, 87 | }, nil 88 | } 89 | 90 | func (c *defaultMetaClient) AddHostsIntoZone(zone string, endpoints []string, isNew bool) (types.MetaBaser, error) { 91 | hostsToAdd := make([]*nthrift.HostAddr, 0, len(endpoints)) 92 | for _, ep := range endpoints { 93 | host, portStr, err := net.SplitHostPort(ep) 94 | if err != nil { 95 | return nil, err 96 | } 97 | 98 | port, err := strconv.Atoi(portStr) 99 | if err != nil { 100 | return nil, err 101 | } 102 | 103 | hostsToAdd = append(hostsToAdd, &nthrift.HostAddr{ 104 | Host: host, 105 | Port: nthrift.Port(port), 106 | }) 107 | } 108 | 109 | req := &meta.AddHostsIntoZoneReq{ 110 | Hosts: hostsToAdd, 111 | ZoneName: []byte(zone), 112 | IsNew: isNew, 113 | } 114 | 115 | fmt.Println(req) 116 | 117 | resp, err := c.meta.AddHostsIntoZone(req) 118 | if err != nil { 119 | return nil, err 120 | } 121 | 122 | return metaBaserWrap{ 123 | code: nerrors.ErrorCode(resp.GetCode()), 124 | leader: types.HostAddr{ 125 | Host: resp.GetLeader().GetHost(), 126 | Port: resp.GetLeader().GetPort(), 127 | }, 128 | }, nil 129 | } 130 | 131 | func (c *defaultMetaClient) DropHosts(endpoints []string) (types.MetaBaser, error) { 132 | hostsToDrop := make([]*nthrift.HostAddr, 0, len(endpoints)) 133 | for _, ep := range endpoints { 134 | host, portStr, err := net.SplitHostPort(ep) 135 | if err != nil { 136 | return nil, err 137 | } 138 | 139 | port, err := strconv.Atoi(portStr) 140 | if err != nil { 141 | return nil, err 142 | } 143 | 144 | hostsToDrop = append(hostsToDrop, &nthrift.HostAddr{ 145 | Host: host, 146 | Port: nthrift.Port(port), 147 | }) 148 | } 149 | 150 | req := &meta.DropHostsReq{ 151 | Hosts: hostsToDrop, 152 | } 153 | resp, err := c.meta.DropHosts(req) 154 | if err != nil { 155 | return nil, err 156 | } 157 | return metaBaserWrap{ 158 | code: nerrors.ErrorCode(resp.GetCode()), 159 | leader: types.HostAddr{ 160 | Host: resp.GetLeader().GetHost(), 161 | Port: resp.GetLeader().GetPort(), 162 | }, 163 | }, nil 164 | } 165 | 166 | func (c *defaultMetaClient) ListSpaces() (types.Spaces, error) { 167 | req := meta.NewListSpacesReq() 168 | 169 | resp, err := c.meta.ListSpaces(req) 170 | if err != nil { 171 | return nil, err 172 | } 173 | 174 | return newSpacesWrapper(resp), nil 175 | } 176 | 177 | func (c *defaultMetaClient) Balance(req types.BalanceReq) (types.Balancer, error) { 178 | paras := make([][]byte, 0) 179 | 180 | var cmd meta.AdminCmd 181 | switch req.Cmd { 182 | case types.BalanceLeader: 183 | cmd = meta.AdminCmd_LEADER_BALANCE 184 | case types.BalanceData: 185 | cmd = meta.AdminCmd_DATA_BALANCE 186 | case types.BalanceDataRemove: 187 | cmd = meta.AdminCmd_DATA_BALANCE 188 | for _, ep := range req.HostsToRemove { 189 | paras = append(paras, []byte(ep)) 190 | } 191 | default: 192 | return nil, nerrors.ErrUnsupported 193 | } 194 | 195 | paras = append(paras, []byte(req.Space)) 196 | metaReq := &meta.AdminJobReq{ 197 | Op: meta.AdminJobOp_ADD, 198 | Cmd: cmd, 199 | Paras: paras, 200 | } 201 | 202 | resp, err := c.meta.RunAdminJob(metaReq) 203 | if err != nil { 204 | return nil, err 205 | } 206 | 207 | return newBalancerWrap(c.meta, req.Space, resp), nil 208 | } 209 | 210 | func (c *defaultMetaClient) ListHosts() (types.Hosts, error) { 211 | req := meta.NewListHostsReq() 212 | 213 | resp, err := c.meta.ListHosts(req) 214 | if err != nil { 215 | return nil, err 216 | } 217 | 218 | return newHostsWrapper(resp), nil 219 | } 220 | 221 | func (c *defaultMetaClient) ListZones() (types.Zones, error) { 222 | req := meta.NewListZonesReq() 223 | 224 | resp, err := c.meta.ListZones(req) 225 | if err != nil { 226 | return nil, err 227 | } 228 | 229 | return newZonesWrapper(resp), nil 230 | } 231 | -------------------------------------------------------------------------------- /ccore/nebula/internal/driver/v3_0/storage_admin.go: -------------------------------------------------------------------------------- 1 | package v3_0 2 | 3 | import ( 4 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 5 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v3_0/storage" 6 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 7 | ) 8 | 9 | var ( 10 | _ types.StorageAdminClientDriver = (*defaultStorageAdminClient)(nil) 11 | ) 12 | 13 | type ( 14 | defaultStorageAdminClient struct { 15 | storageAdmin *storage.StorageAdminServiceClient 16 | } 17 | ) 18 | 19 | func newStorageAdminClient(transport thrift.Transport, pf thrift.ProtocolFactory) types.StorageAdminClientDriver { 20 | return &defaultStorageAdminClient{ 21 | storageAdmin: storage.NewStorageAdminServiceClientFactory(transport, pf), 22 | } 23 | } 24 | 25 | func (c *defaultStorageAdminClient) Open() error { 26 | return c.storageAdmin.Open() 27 | } 28 | 29 | func (c *defaultStorageAdminClient) Close() error { 30 | if c.storageAdmin != nil { 31 | if err := c.storageAdmin.Close(); err != nil { 32 | return err 33 | } 34 | } 35 | return nil 36 | } 37 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v2_5/constants.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package nebula 6 | 7 | import ( 8 | "bytes" 9 | "context" 10 | "fmt" 11 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 12 | "sync" 13 | ) 14 | 15 | // (needed to ensure safety because of naive import list construction.) 16 | var _ = thrift.ZERO 17 | var _ = fmt.Printf 18 | var _ = sync.Mutex{} 19 | var _ = bytes.Equal 20 | var _ = context.Background 21 | 22 | func init() { 23 | } 24 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v2_5/graph/constants.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package graph 6 | 7 | import ( 8 | "bytes" 9 | "context" 10 | "fmt" 11 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 12 | nebula0 "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_5" 13 | "sync" 14 | ) 15 | 16 | // (needed to ensure safety because of naive import list construction.) 17 | var _ = thrift.ZERO 18 | var _ = fmt.Printf 19 | var _ = sync.Mutex{} 20 | var _ = bytes.Equal 21 | var _ = context.Background 22 | 23 | var _ = nebula0.GoUnusedProtection__ 24 | 25 | func init() { 26 | } 27 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v2_5/meta/constants.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package meta 6 | 7 | import ( 8 | "bytes" 9 | "context" 10 | "fmt" 11 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 12 | nebula0 "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_5" 13 | "sync" 14 | ) 15 | 16 | // (needed to ensure safety because of naive import list construction.) 17 | var _ = thrift.ZERO 18 | var _ = fmt.Printf 19 | var _ = sync.Mutex{} 20 | var _ = bytes.Equal 21 | var _ = context.Background 22 | 23 | var _ = nebula0.GoUnusedProtection__ 24 | var const_lit_vid_type_type_length int16 = 8 25 | 26 | func init() { 27 | } 28 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v2_5/storage/constants.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package storage 6 | 7 | import ( 8 | "bytes" 9 | "context" 10 | "fmt" 11 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 12 | nebula0 "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_5" 13 | meta1 "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_5/meta" 14 | "sync" 15 | ) 16 | 17 | // (needed to ensure safety because of naive import list construction.) 18 | var _ = thrift.ZERO 19 | var _ = fmt.Printf 20 | var _ = sync.Mutex{} 21 | var _ = bytes.Equal 22 | var _ = context.Background 23 | 24 | var _ = nebula0.GoUnusedProtection__ 25 | var _ = meta1.GoUnusedProtection__ 26 | 27 | func init() { 28 | } 29 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v2_6/constants.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package nebula 6 | 7 | import ( 8 | "bytes" 9 | "context" 10 | "fmt" 11 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 12 | "sync" 13 | ) 14 | 15 | // (needed to ensure safety because of naive import list construction.) 16 | var _ = thrift.ZERO 17 | var _ = fmt.Printf 18 | var _ = sync.Mutex{} 19 | var _ = bytes.Equal 20 | var _ = context.Background 21 | 22 | const Version = "2.6.0" 23 | 24 | func init() { 25 | } 26 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v2_6/graph/constants.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package graph 6 | 7 | import ( 8 | "bytes" 9 | "context" 10 | "fmt" 11 | "sync" 12 | 13 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 14 | nebula0 "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_6" 15 | ) 16 | 17 | // (needed to ensure safety because of naive import list construction.) 18 | var _ = thrift.ZERO 19 | var _ = fmt.Printf 20 | var _ = sync.Mutex{} 21 | var _ = bytes.Equal 22 | var _ = context.Background 23 | 24 | var _ = nebula0.GoUnusedProtection__ 25 | 26 | func init() { 27 | } 28 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v2_6/meta/constants.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package meta 6 | 7 | import ( 8 | "bytes" 9 | "context" 10 | "fmt" 11 | "sync" 12 | 13 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 14 | nebula0 "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_6" 15 | ) 16 | 17 | // (needed to ensure safety because of naive import list construction.) 18 | var _ = thrift.ZERO 19 | var _ = fmt.Printf 20 | var _ = sync.Mutex{} 21 | var _ = bytes.Equal 22 | var _ = context.Background 23 | 24 | var _ = nebula0.GoUnusedProtection__ 25 | var const_lit_vid_type_type_length int16 = 8 26 | 27 | func init() { 28 | } 29 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v2_6/storage/constants.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package storage 6 | 7 | import ( 8 | "bytes" 9 | "context" 10 | "fmt" 11 | "sync" 12 | 13 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 14 | nebula0 "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_6" 15 | meta1 "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v2_6/meta" 16 | ) 17 | 18 | // (needed to ensure safety because of naive import list construction.) 19 | var _ = thrift.ZERO 20 | var _ = fmt.Printf 21 | var _ = sync.Mutex{} 22 | var _ = bytes.Equal 23 | var _ = context.Background 24 | 25 | var _ = nebula0.GoUnusedProtection__ 26 | var _ = meta1.GoUnusedProtection__ 27 | 28 | func init() { 29 | } 30 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v3_0/constants.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package nebula 6 | 7 | import ( 8 | "bytes" 9 | "context" 10 | "fmt" 11 | "sync" 12 | 13 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 14 | ) 15 | 16 | // (needed to ensure safety because of naive import list construction.) 17 | var _ = thrift.ZERO 18 | var _ = fmt.Printf 19 | var _ = sync.Mutex{} 20 | var _ = bytes.Equal 21 | var _ = context.Background 22 | 23 | const Version = "3.0.0" 24 | 25 | func init() { 26 | } 27 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v3_0/graph/constants.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package graph 6 | 7 | import ( 8 | "bytes" 9 | "context" 10 | "fmt" 11 | "sync" 12 | 13 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 14 | nebula0 "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v3_0" 15 | ) 16 | 17 | // (needed to ensure safety because of naive import list construction.) 18 | var _ = thrift.ZERO 19 | var _ = fmt.Printf 20 | var _ = sync.Mutex{} 21 | var _ = bytes.Equal 22 | var _ = context.Background 23 | 24 | var _ = nebula0.GoUnusedProtection__ 25 | 26 | func init() { 27 | } 28 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v3_0/graph/graph_service-remote/graph_service-remote.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "fmt" 10 | "math" 11 | "net" 12 | "net/url" 13 | "os" 14 | "strconv" 15 | "strings" 16 | 17 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 18 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v3_0/graph" 19 | ) 20 | 21 | func Usage() { 22 | fmt.Fprintln(os.Stderr, "Usage of ", os.Args[0], " [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:") 23 | flag.PrintDefaults() 24 | fmt.Fprintln(os.Stderr, "\nFunctions:") 25 | fmt.Fprintln(os.Stderr, " AuthResponse authenticate(string username, string password)") 26 | fmt.Fprintln(os.Stderr, " void signout(i64 sessionId)") 27 | fmt.Fprintln(os.Stderr, " ExecutionResponse execute(i64 sessionId, string stmt)") 28 | fmt.Fprintln(os.Stderr, " ExecutionResponse executeWithParameter(i64 sessionId, string stmt, parameterMap)") 29 | fmt.Fprintln(os.Stderr, " string executeJson(i64 sessionId, string stmt)") 30 | fmt.Fprintln(os.Stderr, " string executeJsonWithParameter(i64 sessionId, string stmt, parameterMap)") 31 | fmt.Fprintln(os.Stderr, " VerifyClientVersionResp verifyClientVersion(VerifyClientVersionReq req)") 32 | fmt.Fprintln(os.Stderr) 33 | os.Exit(0) 34 | } 35 | 36 | func main() { 37 | flag.Usage = Usage 38 | var host string 39 | var port int 40 | var protocol string 41 | var urlString string 42 | var framed bool 43 | var useHttp bool 44 | var parsedUrl url.URL 45 | var trans thrift.Transport 46 | _ = strconv.Atoi 47 | _ = math.Abs 48 | flag.Usage = Usage 49 | flag.StringVar(&host, "h", "localhost", "Specify host") 50 | flag.IntVar(&port, "p", 9090, "Specify port") 51 | flag.StringVar(&protocol, "P", "binary", "Specify the protocol (binary, compact, simplejson, json)") 52 | flag.StringVar(&urlString, "u", "", "Specify the url") 53 | flag.BoolVar(&framed, "framed", false, "Use framed transport") 54 | flag.BoolVar(&useHttp, "http", false, "Use http") 55 | flag.Parse() 56 | 57 | if len(urlString) > 0 { 58 | parsedUrl, err := url.Parse(urlString) 59 | if err != nil { 60 | fmt.Fprintln(os.Stderr, "Error parsing URL: ", err) 61 | flag.Usage() 62 | } 63 | host = parsedUrl.Host 64 | useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == "http" 65 | } else if useHttp { 66 | _, err := url.Parse(fmt.Sprint("http://", host, ":", port)) 67 | if err != nil { 68 | fmt.Fprintln(os.Stderr, "Error parsing URL: ", err) 69 | flag.Usage() 70 | } 71 | } 72 | 73 | cmd := flag.Arg(0) 74 | var err error 75 | if useHttp { 76 | trans, err = thrift.NewHTTPPostClient(parsedUrl.String()) 77 | } else { 78 | portStr := fmt.Sprint(port) 79 | if strings.Contains(host, ":") { 80 | host, portStr, err = net.SplitHostPort(host) 81 | if err != nil { 82 | fmt.Fprintln(os.Stderr, "error with host:", err) 83 | os.Exit(1) 84 | } 85 | } 86 | trans, err = thrift.NewSocket(thrift.SocketAddr(net.JoinHostPort(host, portStr))) 87 | if err != nil { 88 | fmt.Fprintln(os.Stderr, "error resolving address:", err) 89 | os.Exit(1) 90 | } 91 | if framed { 92 | trans = thrift.NewFramedTransport(trans) 93 | } 94 | } 95 | if err != nil { 96 | fmt.Fprintln(os.Stderr, "Error creating transport", err) 97 | os.Exit(1) 98 | } 99 | defer trans.Close() 100 | var protocolFactory thrift.ProtocolFactory 101 | switch protocol { 102 | case "compact": 103 | protocolFactory = thrift.NewCompactProtocolFactory() 104 | break 105 | case "simplejson": 106 | protocolFactory = thrift.NewSimpleJSONProtocolFactory() 107 | break 108 | case "json": 109 | protocolFactory = thrift.NewJSONProtocolFactory() 110 | break 111 | case "binary", "": 112 | protocolFactory = thrift.NewBinaryProtocolFactoryDefault() 113 | break 114 | default: 115 | fmt.Fprintln(os.Stderr, "Invalid protocol specified: ", protocol) 116 | Usage() 117 | os.Exit(1) 118 | } 119 | client := graph.NewGraphServiceClientFactory(trans, protocolFactory) 120 | if err := trans.Open(); err != nil { 121 | fmt.Fprintln(os.Stderr, "Error opening socket to ", host, ":", port, " ", err) 122 | os.Exit(1) 123 | } 124 | 125 | switch cmd { 126 | case "authenticate": 127 | if flag.NArg()-1 != 2 { 128 | fmt.Fprintln(os.Stderr, "Authenticate requires 2 args") 129 | flag.Usage() 130 | } 131 | argvalue0 := []byte(flag.Arg(1)) 132 | value0 := argvalue0 133 | argvalue1 := []byte(flag.Arg(2)) 134 | value1 := argvalue1 135 | fmt.Print(client.Authenticate(value0, value1)) 136 | fmt.Print("\n") 137 | break 138 | case "signout": 139 | if flag.NArg()-1 != 1 { 140 | fmt.Fprintln(os.Stderr, "Signout requires 1 args") 141 | flag.Usage() 142 | } 143 | argvalue0, err17 := (strconv.ParseInt(flag.Arg(1), 10, 64)) 144 | if err17 != nil { 145 | Usage() 146 | return 147 | } 148 | value0 := argvalue0 149 | fmt.Print(client.Signout(value0)) 150 | fmt.Print("\n") 151 | break 152 | case "execute": 153 | if flag.NArg()-1 != 2 { 154 | fmt.Fprintln(os.Stderr, "Execute requires 2 args") 155 | flag.Usage() 156 | } 157 | argvalue0, err18 := (strconv.ParseInt(flag.Arg(1), 10, 64)) 158 | if err18 != nil { 159 | Usage() 160 | return 161 | } 162 | value0 := argvalue0 163 | argvalue1 := []byte(flag.Arg(2)) 164 | value1 := argvalue1 165 | fmt.Print(client.Execute(value0, value1)) 166 | fmt.Print("\n") 167 | break 168 | case "executeWithParameter": 169 | if flag.NArg()-1 != 3 { 170 | fmt.Fprintln(os.Stderr, "ExecuteWithParameter requires 3 args") 171 | flag.Usage() 172 | } 173 | argvalue0, err20 := (strconv.ParseInt(flag.Arg(1), 10, 64)) 174 | if err20 != nil { 175 | Usage() 176 | return 177 | } 178 | value0 := argvalue0 179 | argvalue1 := []byte(flag.Arg(2)) 180 | value1 := argvalue1 181 | arg22 := flag.Arg(3) 182 | mbTrans23 := thrift.NewMemoryBufferLen(len(arg22)) 183 | defer mbTrans23.Close() 184 | _, err24 := mbTrans23.WriteString(arg22) 185 | if err24 != nil { 186 | Usage() 187 | return 188 | } 189 | factory25 := thrift.NewSimpleJSONProtocolFactory() 190 | jsProt26 := factory25.GetProtocol(mbTrans23) 191 | containerStruct2 := graph.NewGraphServiceExecuteWithParameterArgs() 192 | err27 := containerStruct2.ReadField3(jsProt26) 193 | if err27 != nil { 194 | Usage() 195 | return 196 | } 197 | argvalue2 := containerStruct2.ParameterMap 198 | value2 := argvalue2 199 | fmt.Print(client.ExecuteWithParameter(value0, value1, value2)) 200 | fmt.Print("\n") 201 | break 202 | case "executeJson": 203 | if flag.NArg()-1 != 2 { 204 | fmt.Fprintln(os.Stderr, "ExecuteJson requires 2 args") 205 | flag.Usage() 206 | } 207 | argvalue0, err28 := (strconv.ParseInt(flag.Arg(1), 10, 64)) 208 | if err28 != nil { 209 | Usage() 210 | return 211 | } 212 | value0 := argvalue0 213 | argvalue1 := []byte(flag.Arg(2)) 214 | value1 := argvalue1 215 | fmt.Print(client.ExecuteJson(value0, value1)) 216 | fmt.Print("\n") 217 | break 218 | case "executeJsonWithParameter": 219 | if flag.NArg()-1 != 3 { 220 | fmt.Fprintln(os.Stderr, "ExecuteJsonWithParameter requires 3 args") 221 | flag.Usage() 222 | } 223 | argvalue0, err30 := (strconv.ParseInt(flag.Arg(1), 10, 64)) 224 | if err30 != nil { 225 | Usage() 226 | return 227 | } 228 | value0 := argvalue0 229 | argvalue1 := []byte(flag.Arg(2)) 230 | value1 := argvalue1 231 | arg32 := flag.Arg(3) 232 | mbTrans33 := thrift.NewMemoryBufferLen(len(arg32)) 233 | defer mbTrans33.Close() 234 | _, err34 := mbTrans33.WriteString(arg32) 235 | if err34 != nil { 236 | Usage() 237 | return 238 | } 239 | factory35 := thrift.NewSimpleJSONProtocolFactory() 240 | jsProt36 := factory35.GetProtocol(mbTrans33) 241 | containerStruct2 := graph.NewGraphServiceExecuteJsonWithParameterArgs() 242 | err37 := containerStruct2.ReadField3(jsProt36) 243 | if err37 != nil { 244 | Usage() 245 | return 246 | } 247 | argvalue2 := containerStruct2.ParameterMap 248 | value2 := argvalue2 249 | fmt.Print(client.ExecuteJsonWithParameter(value0, value1, value2)) 250 | fmt.Print("\n") 251 | break 252 | case "verifyClientVersion": 253 | if flag.NArg()-1 != 1 { 254 | fmt.Fprintln(os.Stderr, "VerifyClientVersion requires 1 args") 255 | flag.Usage() 256 | } 257 | arg38 := flag.Arg(1) 258 | mbTrans39 := thrift.NewMemoryBufferLen(len(arg38)) 259 | defer mbTrans39.Close() 260 | _, err40 := mbTrans39.WriteString(arg38) 261 | if err40 != nil { 262 | Usage() 263 | return 264 | } 265 | factory41 := thrift.NewSimpleJSONProtocolFactory() 266 | jsProt42 := factory41.GetProtocol(mbTrans39) 267 | argvalue0 := graph.NewVerifyClientVersionReq() 268 | err43 := argvalue0.Read(jsProt42) 269 | if err43 != nil { 270 | Usage() 271 | return 272 | } 273 | value0 := argvalue0 274 | fmt.Print(client.VerifyClientVersion(value0)) 275 | fmt.Print("\n") 276 | break 277 | case "": 278 | Usage() 279 | break 280 | default: 281 | fmt.Fprintln(os.Stderr, "Invalid function ", cmd) 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v3_0/meta/constants.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package meta 6 | 7 | import ( 8 | "bytes" 9 | "context" 10 | "fmt" 11 | "sync" 12 | 13 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 14 | nebula0 "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v3_0" 15 | ) 16 | 17 | // (needed to ensure safety because of naive import list construction.) 18 | var _ = thrift.ZERO 19 | var _ = fmt.Printf 20 | var _ = sync.Mutex{} 21 | var _ = bytes.Equal 22 | var _ = context.Background 23 | 24 | var _ = nebula0.GoUnusedProtection__ 25 | var const_lit_vid_type_type_length int16 = 8 26 | 27 | func init() { 28 | } 29 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v3_0/storage/constants.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package storage 6 | 7 | import ( 8 | "bytes" 9 | "context" 10 | "fmt" 11 | "sync" 12 | 13 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 14 | nebula0 "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v3_0" 15 | meta1 "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v3_0/meta" 16 | ) 17 | 18 | // (needed to ensure safety because of naive import list construction.) 19 | var _ = thrift.ZERO 20 | var _ = fmt.Printf 21 | var _ = sync.Mutex{} 22 | var _ = bytes.Equal 23 | var _ = context.Background 24 | 25 | var _ = nebula0.GoUnusedProtection__ 26 | var _ = meta1.GoUnusedProtection__ 27 | 28 | func init() { 29 | } 30 | -------------------------------------------------------------------------------- /ccore/nebula/internal/thrift/v3_0/storage/storage_admin_service-remote/storage_admin_service-remote.go: -------------------------------------------------------------------------------- 1 | // Autogenerated by Thrift Compiler (facebook) 2 | // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 3 | // @generated 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "fmt" 10 | "math" 11 | "net" 12 | "net/url" 13 | "os" 14 | "strconv" 15 | "strings" 16 | 17 | thrift "github.com/facebook/fbthrift/thrift/lib/go/thrift" 18 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/internal/thrift/v3_0/storage" 19 | ) 20 | 21 | func Usage() { 22 | fmt.Fprintln(os.Stderr, "Usage of ", os.Args[0], " [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:") 23 | flag.PrintDefaults() 24 | fmt.Fprintln(os.Stderr, "\nFunctions:") 25 | fmt.Fprintln(os.Stderr, " AdminExecResp transLeader(TransLeaderReq req)") 26 | fmt.Fprintln(os.Stderr, " AdminExecResp addPart(AddPartReq req)") 27 | fmt.Fprintln(os.Stderr, " AdminExecResp addLearner(AddLearnerReq req)") 28 | fmt.Fprintln(os.Stderr, " AdminExecResp removePart(RemovePartReq req)") 29 | fmt.Fprintln(os.Stderr, " AdminExecResp memberChange(MemberChangeReq req)") 30 | fmt.Fprintln(os.Stderr, " AdminExecResp waitingForCatchUpData(CatchUpDataReq req)") 31 | fmt.Fprintln(os.Stderr, " CreateCPResp createCheckpoint(CreateCPRequest req)") 32 | fmt.Fprintln(os.Stderr, " AdminExecResp dropCheckpoint(DropCPRequest req)") 33 | fmt.Fprintln(os.Stderr, " AdminExecResp blockingWrites(BlockingSignRequest req)") 34 | fmt.Fprintln(os.Stderr, " AdminExecResp rebuildTagIndex(RebuildIndexRequest req)") 35 | fmt.Fprintln(os.Stderr, " AdminExecResp rebuildEdgeIndex(RebuildIndexRequest req)") 36 | fmt.Fprintln(os.Stderr, " GetLeaderPartsResp getLeaderParts(GetLeaderReq req)") 37 | fmt.Fprintln(os.Stderr, " AdminExecResp checkPeers(CheckPeersReq req)") 38 | fmt.Fprintln(os.Stderr, " AdminExecResp addAdminTask(AddAdminTaskRequest req)") 39 | fmt.Fprintln(os.Stderr, " AdminExecResp stopAdminTask(StopAdminTaskRequest req)") 40 | fmt.Fprintln(os.Stderr) 41 | os.Exit(0) 42 | } 43 | 44 | func main() { 45 | flag.Usage = Usage 46 | var host string 47 | var port int 48 | var protocol string 49 | var urlString string 50 | var framed bool 51 | var useHttp bool 52 | var parsedUrl url.URL 53 | var trans thrift.Transport 54 | _ = strconv.Atoi 55 | _ = math.Abs 56 | flag.Usage = Usage 57 | flag.StringVar(&host, "h", "localhost", "Specify host") 58 | flag.IntVar(&port, "p", 9090, "Specify port") 59 | flag.StringVar(&protocol, "P", "binary", "Specify the protocol (binary, compact, simplejson, json)") 60 | flag.StringVar(&urlString, "u", "", "Specify the url") 61 | flag.BoolVar(&framed, "framed", false, "Use framed transport") 62 | flag.BoolVar(&useHttp, "http", false, "Use http") 63 | flag.Parse() 64 | 65 | if len(urlString) > 0 { 66 | parsedUrl, err := url.Parse(urlString) 67 | if err != nil { 68 | fmt.Fprintln(os.Stderr, "Error parsing URL: ", err) 69 | flag.Usage() 70 | } 71 | host = parsedUrl.Host 72 | useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == "http" 73 | } else if useHttp { 74 | _, err := url.Parse(fmt.Sprint("http://", host, ":", port)) 75 | if err != nil { 76 | fmt.Fprintln(os.Stderr, "Error parsing URL: ", err) 77 | flag.Usage() 78 | } 79 | } 80 | 81 | cmd := flag.Arg(0) 82 | var err error 83 | if useHttp { 84 | trans, err = thrift.NewHTTPPostClient(parsedUrl.String()) 85 | } else { 86 | portStr := fmt.Sprint(port) 87 | if strings.Contains(host, ":") { 88 | host, portStr, err = net.SplitHostPort(host) 89 | if err != nil { 90 | fmt.Fprintln(os.Stderr, "error with host:", err) 91 | os.Exit(1) 92 | } 93 | } 94 | trans, err = thrift.NewSocket(thrift.SocketAddr(net.JoinHostPort(host, portStr))) 95 | if err != nil { 96 | fmt.Fprintln(os.Stderr, "error resolving address:", err) 97 | os.Exit(1) 98 | } 99 | if framed { 100 | trans = thrift.NewFramedTransport(trans) 101 | } 102 | } 103 | if err != nil { 104 | fmt.Fprintln(os.Stderr, "Error creating transport", err) 105 | os.Exit(1) 106 | } 107 | defer trans.Close() 108 | var protocolFactory thrift.ProtocolFactory 109 | switch protocol { 110 | case "compact": 111 | protocolFactory = thrift.NewCompactProtocolFactory() 112 | break 113 | case "simplejson": 114 | protocolFactory = thrift.NewSimpleJSONProtocolFactory() 115 | break 116 | case "json": 117 | protocolFactory = thrift.NewJSONProtocolFactory() 118 | break 119 | case "binary", "": 120 | protocolFactory = thrift.NewBinaryProtocolFactoryDefault() 121 | break 122 | default: 123 | fmt.Fprintln(os.Stderr, "Invalid protocol specified: ", protocol) 124 | Usage() 125 | os.Exit(1) 126 | } 127 | client := storage.NewStorageAdminServiceClientFactory(trans, protocolFactory) 128 | if err := trans.Open(); err != nil { 129 | fmt.Fprintln(os.Stderr, "Error opening socket to ", host, ":", port, " ", err) 130 | os.Exit(1) 131 | } 132 | 133 | switch cmd { 134 | case "transLeader": 135 | if flag.NArg()-1 != 1 { 136 | fmt.Fprintln(os.Stderr, "TransLeader requires 1 args") 137 | flag.Usage() 138 | } 139 | arg221 := flag.Arg(1) 140 | mbTrans222 := thrift.NewMemoryBufferLen(len(arg221)) 141 | defer mbTrans222.Close() 142 | _, err223 := mbTrans222.WriteString(arg221) 143 | if err223 != nil { 144 | Usage() 145 | return 146 | } 147 | factory224 := thrift.NewSimpleJSONProtocolFactory() 148 | jsProt225 := factory224.GetProtocol(mbTrans222) 149 | argvalue0 := storage.NewTransLeaderReq() 150 | err226 := argvalue0.Read(jsProt225) 151 | if err226 != nil { 152 | Usage() 153 | return 154 | } 155 | value0 := argvalue0 156 | fmt.Print(client.TransLeader(value0)) 157 | fmt.Print("\n") 158 | break 159 | case "addPart": 160 | if flag.NArg()-1 != 1 { 161 | fmt.Fprintln(os.Stderr, "AddPart requires 1 args") 162 | flag.Usage() 163 | } 164 | arg227 := flag.Arg(1) 165 | mbTrans228 := thrift.NewMemoryBufferLen(len(arg227)) 166 | defer mbTrans228.Close() 167 | _, err229 := mbTrans228.WriteString(arg227) 168 | if err229 != nil { 169 | Usage() 170 | return 171 | } 172 | factory230 := thrift.NewSimpleJSONProtocolFactory() 173 | jsProt231 := factory230.GetProtocol(mbTrans228) 174 | argvalue0 := storage.NewAddPartReq() 175 | err232 := argvalue0.Read(jsProt231) 176 | if err232 != nil { 177 | Usage() 178 | return 179 | } 180 | value0 := argvalue0 181 | fmt.Print(client.AddPart(value0)) 182 | fmt.Print("\n") 183 | break 184 | case "addLearner": 185 | if flag.NArg()-1 != 1 { 186 | fmt.Fprintln(os.Stderr, "AddLearner requires 1 args") 187 | flag.Usage() 188 | } 189 | arg233 := flag.Arg(1) 190 | mbTrans234 := thrift.NewMemoryBufferLen(len(arg233)) 191 | defer mbTrans234.Close() 192 | _, err235 := mbTrans234.WriteString(arg233) 193 | if err235 != nil { 194 | Usage() 195 | return 196 | } 197 | factory236 := thrift.NewSimpleJSONProtocolFactory() 198 | jsProt237 := factory236.GetProtocol(mbTrans234) 199 | argvalue0 := storage.NewAddLearnerReq() 200 | err238 := argvalue0.Read(jsProt237) 201 | if err238 != nil { 202 | Usage() 203 | return 204 | } 205 | value0 := argvalue0 206 | fmt.Print(client.AddLearner(value0)) 207 | fmt.Print("\n") 208 | break 209 | case "removePart": 210 | if flag.NArg()-1 != 1 { 211 | fmt.Fprintln(os.Stderr, "RemovePart requires 1 args") 212 | flag.Usage() 213 | } 214 | arg239 := flag.Arg(1) 215 | mbTrans240 := thrift.NewMemoryBufferLen(len(arg239)) 216 | defer mbTrans240.Close() 217 | _, err241 := mbTrans240.WriteString(arg239) 218 | if err241 != nil { 219 | Usage() 220 | return 221 | } 222 | factory242 := thrift.NewSimpleJSONProtocolFactory() 223 | jsProt243 := factory242.GetProtocol(mbTrans240) 224 | argvalue0 := storage.NewRemovePartReq() 225 | err244 := argvalue0.Read(jsProt243) 226 | if err244 != nil { 227 | Usage() 228 | return 229 | } 230 | value0 := argvalue0 231 | fmt.Print(client.RemovePart(value0)) 232 | fmt.Print("\n") 233 | break 234 | case "memberChange": 235 | if flag.NArg()-1 != 1 { 236 | fmt.Fprintln(os.Stderr, "MemberChange requires 1 args") 237 | flag.Usage() 238 | } 239 | arg245 := flag.Arg(1) 240 | mbTrans246 := thrift.NewMemoryBufferLen(len(arg245)) 241 | defer mbTrans246.Close() 242 | _, err247 := mbTrans246.WriteString(arg245) 243 | if err247 != nil { 244 | Usage() 245 | return 246 | } 247 | factory248 := thrift.NewSimpleJSONProtocolFactory() 248 | jsProt249 := factory248.GetProtocol(mbTrans246) 249 | argvalue0 := storage.NewMemberChangeReq() 250 | err250 := argvalue0.Read(jsProt249) 251 | if err250 != nil { 252 | Usage() 253 | return 254 | } 255 | value0 := argvalue0 256 | fmt.Print(client.MemberChange(value0)) 257 | fmt.Print("\n") 258 | break 259 | case "waitingForCatchUpData": 260 | if flag.NArg()-1 != 1 { 261 | fmt.Fprintln(os.Stderr, "WaitingForCatchUpData requires 1 args") 262 | flag.Usage() 263 | } 264 | arg251 := flag.Arg(1) 265 | mbTrans252 := thrift.NewMemoryBufferLen(len(arg251)) 266 | defer mbTrans252.Close() 267 | _, err253 := mbTrans252.WriteString(arg251) 268 | if err253 != nil { 269 | Usage() 270 | return 271 | } 272 | factory254 := thrift.NewSimpleJSONProtocolFactory() 273 | jsProt255 := factory254.GetProtocol(mbTrans252) 274 | argvalue0 := storage.NewCatchUpDataReq() 275 | err256 := argvalue0.Read(jsProt255) 276 | if err256 != nil { 277 | Usage() 278 | return 279 | } 280 | value0 := argvalue0 281 | fmt.Print(client.WaitingForCatchUpData(value0)) 282 | fmt.Print("\n") 283 | break 284 | case "createCheckpoint": 285 | if flag.NArg()-1 != 1 { 286 | fmt.Fprintln(os.Stderr, "CreateCheckpoint requires 1 args") 287 | flag.Usage() 288 | } 289 | arg257 := flag.Arg(1) 290 | mbTrans258 := thrift.NewMemoryBufferLen(len(arg257)) 291 | defer mbTrans258.Close() 292 | _, err259 := mbTrans258.WriteString(arg257) 293 | if err259 != nil { 294 | Usage() 295 | return 296 | } 297 | factory260 := thrift.NewSimpleJSONProtocolFactory() 298 | jsProt261 := factory260.GetProtocol(mbTrans258) 299 | argvalue0 := storage.NewCreateCPRequest() 300 | err262 := argvalue0.Read(jsProt261) 301 | if err262 != nil { 302 | Usage() 303 | return 304 | } 305 | value0 := argvalue0 306 | fmt.Print(client.CreateCheckpoint(value0)) 307 | fmt.Print("\n") 308 | break 309 | case "dropCheckpoint": 310 | if flag.NArg()-1 != 1 { 311 | fmt.Fprintln(os.Stderr, "DropCheckpoint requires 1 args") 312 | flag.Usage() 313 | } 314 | arg263 := flag.Arg(1) 315 | mbTrans264 := thrift.NewMemoryBufferLen(len(arg263)) 316 | defer mbTrans264.Close() 317 | _, err265 := mbTrans264.WriteString(arg263) 318 | if err265 != nil { 319 | Usage() 320 | return 321 | } 322 | factory266 := thrift.NewSimpleJSONProtocolFactory() 323 | jsProt267 := factory266.GetProtocol(mbTrans264) 324 | argvalue0 := storage.NewDropCPRequest() 325 | err268 := argvalue0.Read(jsProt267) 326 | if err268 != nil { 327 | Usage() 328 | return 329 | } 330 | value0 := argvalue0 331 | fmt.Print(client.DropCheckpoint(value0)) 332 | fmt.Print("\n") 333 | break 334 | case "blockingWrites": 335 | if flag.NArg()-1 != 1 { 336 | fmt.Fprintln(os.Stderr, "BlockingWrites requires 1 args") 337 | flag.Usage() 338 | } 339 | arg269 := flag.Arg(1) 340 | mbTrans270 := thrift.NewMemoryBufferLen(len(arg269)) 341 | defer mbTrans270.Close() 342 | _, err271 := mbTrans270.WriteString(arg269) 343 | if err271 != nil { 344 | Usage() 345 | return 346 | } 347 | factory272 := thrift.NewSimpleJSONProtocolFactory() 348 | jsProt273 := factory272.GetProtocol(mbTrans270) 349 | argvalue0 := storage.NewBlockingSignRequest() 350 | err274 := argvalue0.Read(jsProt273) 351 | if err274 != nil { 352 | Usage() 353 | return 354 | } 355 | value0 := argvalue0 356 | fmt.Print(client.BlockingWrites(value0)) 357 | fmt.Print("\n") 358 | break 359 | case "rebuildTagIndex": 360 | if flag.NArg()-1 != 1 { 361 | fmt.Fprintln(os.Stderr, "RebuildTagIndex requires 1 args") 362 | flag.Usage() 363 | } 364 | arg275 := flag.Arg(1) 365 | mbTrans276 := thrift.NewMemoryBufferLen(len(arg275)) 366 | defer mbTrans276.Close() 367 | _, err277 := mbTrans276.WriteString(arg275) 368 | if err277 != nil { 369 | Usage() 370 | return 371 | } 372 | factory278 := thrift.NewSimpleJSONProtocolFactory() 373 | jsProt279 := factory278.GetProtocol(mbTrans276) 374 | argvalue0 := storage.NewRebuildIndexRequest() 375 | err280 := argvalue0.Read(jsProt279) 376 | if err280 != nil { 377 | Usage() 378 | return 379 | } 380 | value0 := argvalue0 381 | fmt.Print(client.RebuildTagIndex(value0)) 382 | fmt.Print("\n") 383 | break 384 | case "rebuildEdgeIndex": 385 | if flag.NArg()-1 != 1 { 386 | fmt.Fprintln(os.Stderr, "RebuildEdgeIndex requires 1 args") 387 | flag.Usage() 388 | } 389 | arg281 := flag.Arg(1) 390 | mbTrans282 := thrift.NewMemoryBufferLen(len(arg281)) 391 | defer mbTrans282.Close() 392 | _, err283 := mbTrans282.WriteString(arg281) 393 | if err283 != nil { 394 | Usage() 395 | return 396 | } 397 | factory284 := thrift.NewSimpleJSONProtocolFactory() 398 | jsProt285 := factory284.GetProtocol(mbTrans282) 399 | argvalue0 := storage.NewRebuildIndexRequest() 400 | err286 := argvalue0.Read(jsProt285) 401 | if err286 != nil { 402 | Usage() 403 | return 404 | } 405 | value0 := argvalue0 406 | fmt.Print(client.RebuildEdgeIndex(value0)) 407 | fmt.Print("\n") 408 | break 409 | case "getLeaderParts": 410 | if flag.NArg()-1 != 1 { 411 | fmt.Fprintln(os.Stderr, "GetLeaderParts requires 1 args") 412 | flag.Usage() 413 | } 414 | arg287 := flag.Arg(1) 415 | mbTrans288 := thrift.NewMemoryBufferLen(len(arg287)) 416 | defer mbTrans288.Close() 417 | _, err289 := mbTrans288.WriteString(arg287) 418 | if err289 != nil { 419 | Usage() 420 | return 421 | } 422 | factory290 := thrift.NewSimpleJSONProtocolFactory() 423 | jsProt291 := factory290.GetProtocol(mbTrans288) 424 | argvalue0 := storage.NewGetLeaderReq() 425 | err292 := argvalue0.Read(jsProt291) 426 | if err292 != nil { 427 | Usage() 428 | return 429 | } 430 | value0 := argvalue0 431 | fmt.Print(client.GetLeaderParts(value0)) 432 | fmt.Print("\n") 433 | break 434 | case "checkPeers": 435 | if flag.NArg()-1 != 1 { 436 | fmt.Fprintln(os.Stderr, "CheckPeers requires 1 args") 437 | flag.Usage() 438 | } 439 | arg293 := flag.Arg(1) 440 | mbTrans294 := thrift.NewMemoryBufferLen(len(arg293)) 441 | defer mbTrans294.Close() 442 | _, err295 := mbTrans294.WriteString(arg293) 443 | if err295 != nil { 444 | Usage() 445 | return 446 | } 447 | factory296 := thrift.NewSimpleJSONProtocolFactory() 448 | jsProt297 := factory296.GetProtocol(mbTrans294) 449 | argvalue0 := storage.NewCheckPeersReq() 450 | err298 := argvalue0.Read(jsProt297) 451 | if err298 != nil { 452 | Usage() 453 | return 454 | } 455 | value0 := argvalue0 456 | fmt.Print(client.CheckPeers(value0)) 457 | fmt.Print("\n") 458 | break 459 | case "addAdminTask": 460 | if flag.NArg()-1 != 1 { 461 | fmt.Fprintln(os.Stderr, "AddAdminTask requires 1 args") 462 | flag.Usage() 463 | } 464 | arg299 := flag.Arg(1) 465 | mbTrans300 := thrift.NewMemoryBufferLen(len(arg299)) 466 | defer mbTrans300.Close() 467 | _, err301 := mbTrans300.WriteString(arg299) 468 | if err301 != nil { 469 | Usage() 470 | return 471 | } 472 | factory302 := thrift.NewSimpleJSONProtocolFactory() 473 | jsProt303 := factory302.GetProtocol(mbTrans300) 474 | argvalue0 := storage.NewAddAdminTaskRequest() 475 | err304 := argvalue0.Read(jsProt303) 476 | if err304 != nil { 477 | Usage() 478 | return 479 | } 480 | value0 := argvalue0 481 | fmt.Print(client.AddAdminTask(value0)) 482 | fmt.Print("\n") 483 | break 484 | case "stopAdminTask": 485 | if flag.NArg()-1 != 1 { 486 | fmt.Fprintln(os.Stderr, "StopAdminTask requires 1 args") 487 | flag.Usage() 488 | } 489 | arg305 := flag.Arg(1) 490 | mbTrans306 := thrift.NewMemoryBufferLen(len(arg305)) 491 | defer mbTrans306.Close() 492 | _, err307 := mbTrans306.WriteString(arg305) 493 | if err307 != nil { 494 | Usage() 495 | return 496 | } 497 | factory308 := thrift.NewSimpleJSONProtocolFactory() 498 | jsProt309 := factory308.GetProtocol(mbTrans306) 499 | argvalue0 := storage.NewStopAdminTaskRequest() 500 | err310 := argvalue0.Read(jsProt309) 501 | if err310 != nil { 502 | Usage() 503 | return 504 | } 505 | value0 := argvalue0 506 | fmt.Print(client.StopAdminTask(value0)) 507 | fmt.Print("\n") 508 | break 509 | case "": 510 | Usage() 511 | break 512 | default: 513 | fmt.Fprintln(os.Stderr, "Invalid function ", cmd) 514 | } 515 | } 516 | -------------------------------------------------------------------------------- /ccore/nebula/logger.go: -------------------------------------------------------------------------------- 1 | package nebula 2 | 3 | var ( 4 | _ Logger = noOpLogger{} 5 | ) 6 | 7 | type ( 8 | Logger interface { 9 | Info(...interface{}) 10 | Infof(string, ...interface{}) 11 | Warn(...interface{}) 12 | Warnf(string, ...interface{}) 13 | Error(...interface{}) 14 | Errorf(string, ...interface{}) 15 | Fatal(...interface{}) 16 | Fatalf(string, ...interface{}) 17 | } 18 | ) 19 | 20 | // noOpLogger is used as a placeholder for the default logger 21 | type noOpLogger struct{} 22 | 23 | func (noOpLogger) Info(...interface{}) {} 24 | func (noOpLogger) Infof(string, ...interface{}) {} 25 | func (noOpLogger) Warn(...interface{}) {} 26 | func (noOpLogger) Warnf(string, ...interface{}) {} 27 | func (noOpLogger) Error(...interface{}) {} 28 | func (noOpLogger) Errorf(string, ...interface{}) {} 29 | func (noOpLogger) Fatal(...interface{}) {} 30 | func (noOpLogger) Fatalf(string, ...interface{}) {} 31 | -------------------------------------------------------------------------------- /ccore/nebula/options.go: -------------------------------------------------------------------------------- 1 | package nebula 2 | 3 | import ( 4 | "crypto/tls" 5 | "math" 6 | "time" 7 | ) 8 | 9 | const ( 10 | DefaultTimeout = time.Duration(0) 11 | DefaultBufferSize = 128 << 10 12 | DefaultFrameMaxLength = math.MaxUint32 13 | ) 14 | 15 | type ( 16 | Options struct { 17 | version Version 18 | autoVersions []Version 19 | log Logger 20 | graph socketOptions 21 | meta socketOptions 22 | storageAdmin socketOptions 23 | } 24 | 25 | socketOptions struct { 26 | timeout time.Duration 27 | bufferSize int 28 | frameMaxLength uint32 29 | tlsConfig *tls.Config 30 | } 31 | 32 | Option func(o *Options) 33 | ) 34 | 35 | func WithVersion(version Version) Option { 36 | return func(o *Options) { 37 | o.version = version 38 | } 39 | } 40 | 41 | func WithAutoVersions(autoVersions ...Version) Option { 42 | return func(o *Options) { 43 | o.version = versionAuto 44 | if len(autoVersions) > 0 { 45 | o.autoVersions = autoVersions 46 | } 47 | } 48 | } 49 | 50 | func WithLogger(log Logger) Option { 51 | return func(o *Options) { 52 | o.log = log 53 | } 54 | } 55 | 56 | func WithTimeout(timeout time.Duration) Option { 57 | return func(o *Options) { 58 | WithGraphTimeout(timeout)(o) 59 | WithMetaTimeout(timeout)(o) 60 | WithStorageTimeout(timeout)(o) 61 | } 62 | } 63 | 64 | func WithGraphTimeout(timeout time.Duration) Option { 65 | return func(o *Options) { 66 | o.graph.timeout = timeout 67 | } 68 | } 69 | 70 | func WithMetaTimeout(timeout time.Duration) Option { 71 | return func(o *Options) { 72 | o.meta.timeout = timeout 73 | } 74 | } 75 | 76 | func WithStorageTimeout(timeout time.Duration) Option { 77 | return func(o *Options) { 78 | o.storageAdmin.timeout = timeout 79 | } 80 | } 81 | 82 | func WithBufferSize(bufferSize int) Option { 83 | return func(o *Options) { 84 | WithMetaBufferSize(bufferSize) 85 | WithGraphBufferSize(bufferSize) 86 | WithStorageBufferSize(bufferSize) 87 | } 88 | } 89 | 90 | func WithGraphBufferSize(bufferSize int) Option { 91 | return func(o *Options) { 92 | o.graph.bufferSize = bufferSize 93 | } 94 | } 95 | 96 | func WithMetaBufferSize(bufferSize int) Option { 97 | return func(o *Options) { 98 | o.meta.bufferSize = bufferSize 99 | } 100 | } 101 | 102 | func WithStorageBufferSize(bufferSize int) Option { 103 | return func(o *Options) { 104 | o.storageAdmin.bufferSize = bufferSize 105 | } 106 | } 107 | 108 | func WithFrameMaxLength(frameMaxLength uint32) Option { 109 | return func(o *Options) { 110 | WithGraphFrameMaxLength(frameMaxLength) 111 | WithMetaFrameMaxLength(frameMaxLength) 112 | WithStorageFrameMaxLength(frameMaxLength) 113 | } 114 | } 115 | 116 | func WithGraphFrameMaxLength(frameMaxLength uint32) Option { 117 | return func(o *Options) { 118 | o.graph.frameMaxLength = frameMaxLength 119 | } 120 | } 121 | 122 | func WithMetaFrameMaxLength(frameMaxLength uint32) Option { 123 | return func(o *Options) { 124 | o.meta.frameMaxLength = frameMaxLength 125 | } 126 | } 127 | 128 | func WithStorageFrameMaxLength(frameMaxLength uint32) Option { 129 | return func(o *Options) { 130 | o.storageAdmin.frameMaxLength = frameMaxLength 131 | } 132 | } 133 | 134 | func WithTLS(tlsConfig *tls.Config) Option { 135 | return func(o *Options) { 136 | WithGraphTLS(tlsConfig) 137 | WithMetaTLS(tlsConfig) 138 | WithStorageTLS(tlsConfig) 139 | } 140 | } 141 | 142 | func WithGraphTLS(tlsConfig *tls.Config) Option { 143 | return func(o *Options) { 144 | o.graph.tlsConfig = tlsConfig 145 | } 146 | } 147 | 148 | func WithMetaTLS(tlsConfig *tls.Config) Option { 149 | return func(o *Options) { 150 | o.meta.tlsConfig = tlsConfig 151 | } 152 | } 153 | 154 | func WithStorageTLS(tlsConfig *tls.Config) Option { 155 | return func(o *Options) { 156 | o.storageAdmin.tlsConfig = tlsConfig 157 | } 158 | } 159 | 160 | func (o *Options) complete() { 161 | defaultOpts := defaultOptions() 162 | 163 | if o.log == nil { 164 | o.log = defaultOpts.log 165 | } 166 | o.graph.complete() 167 | o.meta.complete() 168 | o.storageAdmin.complete() 169 | } 170 | 171 | func (o *Options) validate() error { 172 | return nil 173 | } 174 | 175 | func (o *socketOptions) complete() { 176 | defaultOpts := defaultSocketOptions() 177 | if o.timeout < 0 { 178 | o.timeout = defaultOpts.timeout 179 | } 180 | if o.bufferSize <= 0 { 181 | o.bufferSize = defaultOpts.bufferSize 182 | } 183 | if o.frameMaxLength <= 0 { 184 | o.frameMaxLength = defaultOpts.frameMaxLength 185 | } 186 | } 187 | 188 | func defaultOptions() Options { 189 | return Options{ 190 | version: versionAuto, 191 | autoVersions: supportedVersions, 192 | log: noOpLogger{}, 193 | graph: defaultSocketOptions(), 194 | meta: defaultSocketOptions(), 195 | storageAdmin: defaultSocketOptions(), 196 | } 197 | } 198 | 199 | func defaultSocketOptions() socketOptions { 200 | return socketOptions{ 201 | timeout: DefaultTimeout, 202 | bufferSize: DefaultBufferSize, 203 | frameMaxLength: DefaultFrameMaxLength, 204 | tlsConfig: nil, 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /ccore/nebula/types/builder.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type ValueBuilder interface { 4 | NVal(*NullType) ValueBuilder 5 | BVal(*bool) ValueBuilder 6 | IVal(*int64) ValueBuilder 7 | FVal(*float64) ValueBuilder 8 | SVal([]byte) ValueBuilder 9 | DVal(Date) ValueBuilder 10 | TVal(Time) ValueBuilder 11 | DtVal(DateTime) ValueBuilder 12 | VVal(Vertex) ValueBuilder 13 | EVal(Edge) ValueBuilder 14 | PVal(Path) ValueBuilder 15 | LVal(NList) ValueBuilder 16 | MVal(NMap) ValueBuilder 17 | UVal(NSet) ValueBuilder 18 | GVal(DataSet) ValueBuilder 19 | GgVal(Geography) ValueBuilder 20 | DuVal(Duration) ValueBuilder 21 | Build() Value 22 | } 23 | 24 | type DateBuilder interface { 25 | Year(int16) DateBuilder 26 | Month(int8) DateBuilder 27 | Day(int8) DateBuilder 28 | Build() Date 29 | } 30 | 31 | type TimeBuilder interface { 32 | Hour(int8) TimeBuilder 33 | Minute(int8) TimeBuilder 34 | Sec(int8) TimeBuilder 35 | Microsec(int32) TimeBuilder 36 | Build() Time 37 | } 38 | 39 | type DateTimeBuilder interface { 40 | Year(int16) DateTimeBuilder 41 | Month(int8) DateTimeBuilder 42 | Day(int8) DateTimeBuilder 43 | Hour(int8) DateTimeBuilder 44 | Minute(int8) DateTimeBuilder 45 | Sec(int8) DateTimeBuilder 46 | Microsec(int32) DateTimeBuilder 47 | Build() DateTime 48 | } 49 | 50 | type EdgeBuilder interface { 51 | Src(Value) EdgeBuilder 52 | Dst(Value) EdgeBuilder 53 | Type(EdgeType) EdgeBuilder 54 | Name([]byte) EdgeBuilder 55 | Ranking(EdgeRanking) EdgeBuilder 56 | Props(map[string]Value) EdgeBuilder 57 | Build() Edge 58 | } 59 | 60 | type NListBuilder interface { 61 | Values([]Value) NListBuilder 62 | Build() NList 63 | } 64 | 65 | type NMapBuilder interface { 66 | Kvs(map[string]Value) NMapBuilder 67 | Build() NMap 68 | } 69 | -------------------------------------------------------------------------------- /ccore/nebula/types/driver.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/facebook/fbthrift/thrift/lib/go/thrift" 7 | nerrors "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/errors" 8 | ) 9 | 10 | var ( 11 | driversMu sync.RWMutex 12 | drivers = make(map[Version]Driver) 13 | 14 | factoryDriversMu sync.RWMutex 15 | factoryDrivers = make(map[Version]FactoryDriver) 16 | ) 17 | 18 | type ( 19 | Driver interface { 20 | NewGraphClientDriver(thrift.Transport, thrift.ProtocolFactory) GraphClientDriver 21 | NewMetaClientDriver(thrift.Transport, thrift.ProtocolFactory) MetaClientDriver 22 | NewStorageClientDriver(thrift.Transport, thrift.ProtocolFactory) StorageAdminClientDriver 23 | } 24 | 25 | GraphClientDriver interface { 26 | Open() error 27 | VerifyClientVersion() error 28 | Authenticate(username, password string) (AuthResponse, error) 29 | Signout(sessionId int64) (err error) 30 | Execute(sessionId int64, stmt []byte) (ExecutionResponse, error) 31 | ExecuteJson(sessionId int64, stmt []byte) ([]byte, error) 32 | ExecuteWithParameter(sessionId int64, stmt []byte, params map[string]Value) (ExecutionResponse, error) 33 | Close() error 34 | } 35 | 36 | MetaClientDriver interface { 37 | Open() error 38 | VerifyClientVersion() error 39 | AddHosts(endpoints []string) (MetaBaser, error) 40 | AddHostsIntoZone(zone string, endpoints []string, isNew bool) (MetaBaser, error) 41 | DropHosts(endpoints []string) (MetaBaser, error) 42 | ListSpaces() (Spaces, error) 43 | Balance(req BalanceReq) (Balancer, error) 44 | ListHosts() (Hosts, error) 45 | ListZones() (Zones, error) 46 | Close() error 47 | } 48 | 49 | StorageAdminClientDriver interface { 50 | Open() error 51 | Close() error 52 | } 53 | 54 | AuthResponse interface { 55 | SessionID() *int64 56 | GetTimezoneInfo() TimezoneInfo 57 | } 58 | 59 | ExecutionResponse interface { 60 | GetLatencyInUs() int64 61 | GetData() DataSet 62 | GetSpaceName() []byte 63 | GetPlanDesc() PlanDescription 64 | GetComment() []byte 65 | GetErrorCode() nerrors.ErrorCode 66 | GetErrorMsg() []byte 67 | IsSetData() bool 68 | IsSetSpaceName() bool 69 | IsSetErrorMsg() bool 70 | IsSetPlanDesc() bool 71 | IsSetComment() bool 72 | String() string 73 | } 74 | 75 | Space interface { 76 | GetName() string 77 | GetId() int32 78 | } 79 | 80 | Spaces interface { 81 | MetaBaser 82 | GetSpaces() []Space 83 | } 84 | 85 | Balancer interface { 86 | MetaBaser 87 | GetStats() (BalanceStats, error) 88 | } 89 | 90 | FactoryDriver interface { 91 | NewValueBuilder() ValueBuilder 92 | NewDateBuilder() DateBuilder 93 | NewTimeBuilder() TimeBuilder 94 | NewDateTimeBuilder() DateTimeBuilder 95 | NewEdgeBuilder() EdgeBuilder 96 | NewNListBuilder() NListBuilder 97 | NewNMapBuilder() NMapBuilder 98 | } 99 | 100 | Host interface { 101 | GetHostItem() HostItem 102 | } 103 | 104 | Hosts interface { 105 | MetaBaser 106 | GetHosts() []Host 107 | } 108 | 109 | Zone interface { 110 | GetName() string 111 | GetHosts() []*HostAddr 112 | } 113 | 114 | Zones interface { 115 | MetaBaser 116 | GetZones() []Zone 117 | } 118 | 119 | Coder interface { 120 | GetCode() nerrors.ErrorCode 121 | } 122 | 123 | MetaBaser interface { 124 | Coder 125 | GetLeader() string 126 | } 127 | ) 128 | 129 | func Register(version Version, driver Driver, factory FactoryDriver) { 130 | registerDriver(version, driver) 131 | registerFactoryDriver(version, factory) 132 | } 133 | 134 | func registerDriver(version Version, driver Driver) { 135 | driversMu.Lock() 136 | defer driversMu.Unlock() 137 | if driver == nil { 138 | panic("nebula: Register driver is nil") 139 | } 140 | if _, dup := drivers[version]; dup { 141 | panic("nebula: Register called twice for driver " + version) 142 | } 143 | drivers[version] = driver 144 | } 145 | 146 | func registerFactoryDriver(version Version, factory FactoryDriver) { 147 | factoryDriversMu.Lock() 148 | defer factoryDriversMu.Unlock() 149 | if factory == nil { 150 | panic("nebula: Register factory driver is nil") 151 | } 152 | if _, dup := factoryDrivers[version]; dup { 153 | panic("nebula: Register called twice for factory driver " + version) 154 | } 155 | factoryDrivers[version] = factory 156 | } 157 | 158 | func Drivers() []Version { 159 | driversMu.RLock() 160 | defer driversMu.RUnlock() 161 | list := make([]Version, 0, len(drivers)) 162 | for version := range drivers { 163 | list = append(list, version) 164 | } 165 | return list 166 | } 167 | 168 | func GetDriver(version Version) (Driver, error) { 169 | driversMu.RLock() 170 | driver, ok := drivers[version] 171 | driversMu.RUnlock() 172 | if !ok { 173 | return nil, nerrors.ErrUnsupportedVersion 174 | } 175 | return driver, nil 176 | } 177 | 178 | func GetFactoryDriver(version Version) (FactoryDriver, error) { 179 | factoryDriversMu.RLock() 180 | factory, ok := factoryDrivers[version] 181 | factoryDriversMu.RUnlock() 182 | if !ok { 183 | return nil, nerrors.ErrUnsupportedVersion 184 | } 185 | return factory, nil 186 | } 187 | -------------------------------------------------------------------------------- /ccore/nebula/types/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Any = interface{} 8 | 9 | type ParameterList []string 10 | type ParameterMap map[string]interface{} 11 | 12 | /* 13 | define the interfaces to fit internal//thrift/ttypes and internal//thrift/graph/ttypes 14 | */ 15 | 16 | type TimezoneInfo struct { 17 | offset int32 18 | name []byte 19 | } 20 | 21 | func (t *TimezoneInfo) GetOffset() int32 { 22 | return t.offset 23 | } 24 | 25 | func (t *TimezoneInfo) GetName() []byte { 26 | return t.name 27 | } 28 | 29 | func (t *TimezoneInfo) SetOffset(offset int32) *TimezoneInfo { 30 | t.offset = offset 31 | return t 32 | } 33 | 34 | func (t *TimezoneInfo) SetName(name []byte) *TimezoneInfo { 35 | t.name = name 36 | return t 37 | } 38 | 39 | type EdgeType = int32 40 | 41 | type EdgeRanking = int64 42 | 43 | type DataSet interface { 44 | GetColumnNames() [][]byte 45 | GetRows() []Row 46 | String() string 47 | Unwrap() interface{} 48 | } 49 | 50 | type Row interface { 51 | GetValues() []Value 52 | String() string 53 | Unwrap() interface{} 54 | } 55 | 56 | type Value interface { 57 | GetNVal() NullType 58 | GetBVal() bool 59 | GetIVal() int64 60 | GetFVal() float64 61 | GetSVal() []byte 62 | GetDVal() Date 63 | GetTVal() Time 64 | GetDtVal() DateTime 65 | GetVVal() Vertex 66 | GetEVal() Edge 67 | GetPVal() Path 68 | GetLVal() NList 69 | GetMVal() NMap 70 | GetUVal() NSet 71 | GetGVal() DataSet 72 | GetGgVal() Geography 73 | GetDuVal() Duration 74 | CountSetFieldsValue() int 75 | IsSetNVal() bool 76 | IsSetBVal() bool 77 | IsSetIVal() bool 78 | IsSetFVal() bool 79 | IsSetSVal() bool 80 | IsSetDVal() bool 81 | IsSetTVal() bool 82 | IsSetDtVal() bool 83 | IsSetVVal() bool 84 | IsSetEVal() bool 85 | IsSetPVal() bool 86 | IsSetLVal() bool 87 | IsSetMVal() bool 88 | IsSetUVal() bool 89 | IsSetGVal() bool 90 | IsSetGgVal() bool 91 | IsSetDuVal() bool 92 | SetNVal(*NullType) Value 93 | SetBVal(*bool) Value 94 | SetIVal(*int64) Value 95 | SetFVal(*float64) Value 96 | SetSVal([]byte) Value 97 | SetDVal(Date) Value 98 | SetTVal(Time) Value 99 | SetDtVal(DateTime) Value 100 | SetVVal(Vertex) Value 101 | SetEVal(Edge) Value 102 | SetPVal(Path) Value 103 | SetLVal(NList) Value 104 | SetMVal(NMap) Value 105 | SetUVal(NSet) Value 106 | SetGVal(DataSet) Value 107 | SetGgVal(Geography) Value 108 | SetDuVal(Duration) Value 109 | String() string 110 | Unwrap() interface{} 111 | } 112 | 113 | type NullType int64 114 | 115 | const ( 116 | NullType___NULL__ NullType = 0 117 | NullType_NaN NullType = 1 118 | NullType_BAD_DATA NullType = 2 119 | NullType_BAD_TYPE NullType = 3 120 | NullType_ERR_OVERFLOW NullType = 4 121 | NullType_UNKNOWN_PROP NullType = 5 122 | NullType_DIV_BY_ZERO NullType = 6 123 | NullType_OUT_OF_RANGE NullType = 7 124 | ) 125 | 126 | var NullTypeToName = map[NullType]string{ 127 | NullType___NULL__: "__NULL__", 128 | NullType_NaN: "NaN", 129 | NullType_BAD_DATA: "BAD_DATA", 130 | NullType_BAD_TYPE: "BAD_TYPE", 131 | NullType_ERR_OVERFLOW: "ERR_OVERFLOW", 132 | NullType_UNKNOWN_PROP: "UNKNOWN_PROP", 133 | NullType_DIV_BY_ZERO: "DIV_BY_ZERO", 134 | NullType_OUT_OF_RANGE: "OUT_OF_RANGE", 135 | } 136 | 137 | var NullTypeToValue = map[string]NullType{ 138 | "__NULL__": NullType___NULL__, 139 | "NaN": NullType_NaN, 140 | "BAD_DATA": NullType_BAD_DATA, 141 | "BAD_TYPE": NullType_BAD_TYPE, 142 | "ERR_OVERFLOW": NullType_ERR_OVERFLOW, 143 | "UNKNOWN_PROP": NullType_UNKNOWN_PROP, 144 | "DIV_BY_ZERO": NullType_DIV_BY_ZERO, 145 | "OUT_OF_RANGE": NullType_OUT_OF_RANGE, 146 | } 147 | 148 | var NullTypeNames = []string{ 149 | "__NULL__", 150 | "NaN", 151 | "BAD_DATA", 152 | "BAD_TYPE", 153 | "ERR_OVERFLOW", 154 | "UNKNOWN_PROP", 155 | "DIV_BY_ZERO", 156 | "OUT_OF_RANGE", 157 | } 158 | 159 | var NullTypeValues = []NullType{ 160 | NullType___NULL__, 161 | NullType_NaN, 162 | NullType_BAD_DATA, 163 | NullType_BAD_TYPE, 164 | NullType_ERR_OVERFLOW, 165 | NullType_UNKNOWN_PROP, 166 | NullType_DIV_BY_ZERO, 167 | NullType_OUT_OF_RANGE, 168 | } 169 | 170 | func (p NullType) String() string { 171 | if v, ok := NullTypeToName[p]; ok { 172 | return v 173 | } 174 | return "" 175 | } 176 | 177 | func NullTypeFromString(s string) (NullType, error) { 178 | if v, ok := NullTypeToValue[s]; ok { 179 | return v, nil 180 | } 181 | return NullType(0), fmt.Errorf("not a valid NullType string") 182 | } 183 | 184 | func NullTypePtr(v NullType) *NullType { return &v } 185 | 186 | type Date interface { 187 | GetYear() int16 188 | GetMonth() int8 189 | GetDay() int8 190 | SetYear(int16) Date 191 | SetMonth(int8) Date 192 | SetDay(int8) Date 193 | String() string 194 | Unwrap() interface{} 195 | } 196 | 197 | type Time interface { 198 | GetHour() int8 199 | GetMinute() int8 200 | GetSec() int8 201 | GetMicrosec() int32 202 | SetHour(int8) Time 203 | SetMinute(int8) Time 204 | SetSec(int8) Time 205 | SetMicrosec(int32) Time 206 | String() string 207 | Unwrap() interface{} 208 | } 209 | 210 | type DateTime interface { 211 | GetYear() int16 212 | GetMonth() int8 213 | GetDay() int8 214 | GetHour() int8 215 | GetMinute() int8 216 | GetSec() int8 217 | GetMicrosec() int32 218 | SetYear(int16) DateTime 219 | SetMonth(int8) DateTime 220 | SetDay(int8) DateTime 221 | SetHour(int8) DateTime 222 | SetMinute(int8) DateTime 223 | SetSec(int8) DateTime 224 | SetMicrosec(int32) DateTime 225 | String() string 226 | Unwrap() interface{} 227 | } 228 | 229 | type Vertex interface { 230 | GetVid() Value 231 | GetTags() []Tag 232 | IsSetVid() bool 233 | String() string 234 | Unwrap() interface{} 235 | } 236 | 237 | type Edge interface { 238 | GetSrc() Value 239 | GetDst() Value 240 | GetType() EdgeType 241 | GetName() []byte 242 | GetRanking() EdgeRanking 243 | GetProps() map[string]Value 244 | IsSetSrc() bool 245 | IsSetDst() bool 246 | SetSrc(Value) Edge 247 | SetDst(Value) Edge 248 | SetType(EdgeType) Edge 249 | SetName([]byte) Edge 250 | SetRanking(EdgeRanking) Edge 251 | SetProps(map[string]Value) Edge 252 | String() string 253 | Unwrap() interface{} 254 | } 255 | 256 | type Path interface { 257 | GetSrc() Vertex 258 | GetSteps() []Step 259 | IsSetSrc() bool 260 | String() string 261 | Unwrap() interface{} 262 | } 263 | 264 | type NList interface { 265 | GetValues() []Value 266 | SetValues([]Value) NList 267 | String() string 268 | Unwrap() interface{} 269 | } 270 | 271 | type NMap interface { 272 | GetKvs() map[string]Value 273 | SetKvs(map[string]Value) NMap 274 | String() string 275 | Unwrap() interface{} 276 | } 277 | 278 | type NSet interface { 279 | GetValues() []Value 280 | String() string 281 | Unwrap() interface{} 282 | } 283 | 284 | type Geography interface { 285 | GetPtVal() Point 286 | GetLsVal() LineString 287 | GetPgVal() Polygon 288 | CountSetFieldsGeography() int 289 | IsSetPtVal() bool 290 | IsSetLsVal() bool 291 | IsSetPgVal() bool 292 | String() string 293 | Unwrap() interface{} 294 | } 295 | 296 | type Tag interface { 297 | GetName() []byte 298 | GetProps() map[string]Value 299 | String() string 300 | Unwrap() interface{} 301 | } 302 | 303 | type Step interface { 304 | GetDst() Vertex 305 | GetType() EdgeType 306 | GetName() []byte 307 | GetRanking() EdgeRanking 308 | GetProps() map[string]Value 309 | IsSetDst() bool 310 | String() string 311 | Unwrap() interface{} 312 | } 313 | 314 | type Point interface { 315 | GetCoord() Coordinate 316 | IsSetCoord() bool 317 | String() string 318 | Unwrap() interface{} 319 | } 320 | 321 | type LineString interface { 322 | GetCoordList() []Coordinate 323 | String() string 324 | Unwrap() interface{} 325 | } 326 | 327 | type Polygon interface { 328 | GetCoordListList() [][]Coordinate 329 | String() string 330 | Unwrap() interface{} 331 | } 332 | 333 | type Coordinate interface { 334 | GetX() float64 335 | GetY() float64 336 | String() string 337 | Unwrap() interface{} 338 | } 339 | 340 | type Duration interface { 341 | GetSeconds() int64 342 | GetMicroseconds() int32 343 | GetMonths() int32 344 | String() string 345 | Unwrap() interface{} 346 | } 347 | 348 | type PlanDescription interface { 349 | GetPlanNodeDescs() []PlanNodeDescription 350 | GetNodeIndexMap() map[int64]int64 351 | GetFormat() []byte 352 | GetOptimizeTimeInUs() int32 353 | String() string 354 | Unwrap() interface{} 355 | } 356 | 357 | type PlanNodeDescription interface { 358 | GetName() []byte 359 | GetId() int64 360 | GetOutputVar() []byte 361 | GetDescription() []Pair 362 | GetProfiles() []ProfilingStats 363 | GetBranchInfo() PlanNodeBranchInfo 364 | GetDependencies() []int64 365 | IsSetDescription() bool 366 | IsSetProfiles() bool 367 | IsSetBranchInfo() bool 368 | IsSetDependencies() bool 369 | String() string 370 | Unwrap() interface{} 371 | } 372 | 373 | type Pair interface { 374 | GetKey() []byte 375 | GetValue() []byte 376 | String() string 377 | Unwrap() interface{} 378 | } 379 | 380 | type ProfilingStats interface { 381 | GetRows() int64 382 | GetExecDurationInUs() int64 383 | GetTotalDurationInUs() int64 384 | GetOtherStats() map[string][]byte 385 | IsSetOtherStats() bool 386 | String() string 387 | Unwrap() interface{} 388 | } 389 | 390 | type PlanNodeBranchInfo interface { 391 | GetIsDoBranch() bool 392 | GetConditionNodeID() int64 393 | String() string 394 | Unwrap() interface{} 395 | } 396 | 397 | type ( 398 | BalanceCmd string 399 | BalanceStats string 400 | ) 401 | 402 | const ( 403 | BalanceData = BalanceCmd("Balance Data") 404 | BalanceDataRemove = BalanceCmd("Balance Data Remove") 405 | BalanceLeader = BalanceCmd("Balance Leader") 406 | 407 | Balanced = BalanceStats("Balanced") 408 | Unbalanced = BalanceStats("Unbalanced") 409 | Balancing = BalanceStats("Balancing") 410 | ) 411 | 412 | type BalanceReq struct { 413 | Cmd BalanceCmd 414 | Space string 415 | HostsToRemove []string 416 | } 417 | 418 | type ( 419 | HostStatus int64 420 | ) 421 | 422 | type HostItem struct { 423 | HostAddr HostAddr 424 | Status HostStatus 425 | LeaderParts map[string][]int32 426 | AllParts map[string][]int32 427 | Role int64 428 | GitInfoSha []byte 429 | ZoneName []byte 430 | Version []byte 431 | } 432 | 433 | type HostAddr struct { 434 | Host string 435 | Port int32 436 | } 437 | -------------------------------------------------------------------------------- /ccore/nebula/types/version.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type Version string 4 | 5 | const ( 6 | Version2_5 = Version("v2.5") 7 | Version2_6 = Version("v2.6") 8 | Version3_0 = Version("v3.0") 9 | ) 10 | -------------------------------------------------------------------------------- /ccore/nebula/wrapper/value_wrapper.go: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2020 vesoft inc. All rights reserved. 4 | * 5 | * This source code is licensed under Apache 2.0 License. 6 | * 7 | */ 8 | 9 | package wrapper 10 | 11 | import ( 12 | "fmt" 13 | "sort" 14 | "strconv" 15 | "strings" 16 | 17 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 18 | ) 19 | 20 | /* 21 | copy from nebula-go and fit with ccore/nebula/types 22 | */ 23 | 24 | type ValueWrapper struct { 25 | value types.Value 26 | factory types.FactoryDriver 27 | timezoneInfo types.TimezoneInfo 28 | } 29 | 30 | func (valWrap ValueWrapper) IsEmpty() bool { 31 | return valWrap.GetType() == "empty" 32 | } 33 | 34 | func (valWrap ValueWrapper) IsNull() bool { 35 | return valWrap.value.IsSetNVal() 36 | } 37 | 38 | func (valWrap ValueWrapper) IsBool() bool { 39 | return valWrap.value.IsSetBVal() 40 | } 41 | 42 | func (valWrap ValueWrapper) IsInt() bool { 43 | return valWrap.value.IsSetIVal() 44 | } 45 | 46 | func (valWrap ValueWrapper) IsFloat() bool { 47 | return valWrap.value.IsSetFVal() 48 | } 49 | 50 | func (valWrap ValueWrapper) IsString() bool { 51 | return valWrap.value.IsSetSVal() 52 | } 53 | 54 | func (valWrap ValueWrapper) IsTime() bool { 55 | return valWrap.value.IsSetTVal() 56 | } 57 | 58 | func (valWrap ValueWrapper) IsDate() bool { 59 | return valWrap.value.IsSetDVal() 60 | } 61 | 62 | func (valWrap ValueWrapper) IsDateTime() bool { 63 | return valWrap.value.IsSetDtVal() 64 | } 65 | 66 | func (valWrap ValueWrapper) IsList() bool { 67 | return valWrap.value.IsSetLVal() 68 | } 69 | 70 | func (valWrap ValueWrapper) IsSet() bool { 71 | return valWrap.value.IsSetUVal() 72 | } 73 | 74 | func (valWrap ValueWrapper) IsMap() bool { 75 | return valWrap.value.IsSetMVal() 76 | } 77 | 78 | func (valWrap ValueWrapper) IsVertex() bool { 79 | return valWrap.value.IsSetVVal() 80 | } 81 | 82 | func (valWrap ValueWrapper) IsEdge() bool { 83 | return valWrap.value.IsSetEVal() 84 | } 85 | 86 | func (valWrap ValueWrapper) IsPath() bool { 87 | return valWrap.value.IsSetPVal() 88 | } 89 | 90 | func (valWrap ValueWrapper) IsGeography() bool { 91 | return valWrap.value.IsSetGgVal() 92 | } 93 | 94 | func (valWrap ValueWrapper) IsDuration() bool { 95 | return valWrap.value.IsSetDuVal() 96 | } 97 | 98 | // AsNull converts the ValueWrapper to types.NullType 99 | func (valWrap ValueWrapper) AsNull() (types.NullType, error) { 100 | if valWrap.value.IsSetNVal() { 101 | return valWrap.value.GetNVal(), nil 102 | } 103 | return -1, fmt.Errorf("failed to convert value %s to Null", valWrap.GetType()) 104 | } 105 | 106 | // AsBool converts the ValueWrapper to a boolean value 107 | func (valWrap ValueWrapper) AsBool() (bool, error) { 108 | if valWrap.value.IsSetBVal() { 109 | return valWrap.value.GetBVal(), nil 110 | } 111 | return false, fmt.Errorf("failed to convert value %s to bool", valWrap.GetType()) 112 | } 113 | 114 | // AsInt converts the ValueWrapper to an int64 115 | func (valWrap ValueWrapper) AsInt() (int64, error) { 116 | if valWrap.value.IsSetIVal() { 117 | return valWrap.value.GetIVal(), nil 118 | } 119 | return -1, fmt.Errorf("failed to convert value %s to int", valWrap.GetType()) 120 | } 121 | 122 | // AsFloat converts the ValueWrapper to a float64 123 | func (valWrap ValueWrapper) AsFloat() (float64, error) { 124 | if valWrap.value.IsSetFVal() { 125 | return valWrap.value.GetFVal(), nil 126 | } 127 | return -1, fmt.Errorf("failed to convert value %s to float", valWrap.GetType()) 128 | } 129 | 130 | // AsString converts the ValueWrapper to a String 131 | func (valWrap ValueWrapper) AsString() (string, error) { 132 | if valWrap.value.IsSetSVal() { 133 | return string(valWrap.value.GetSVal()), nil 134 | } 135 | return "", fmt.Errorf("failed to convert value %s to string", valWrap.GetType()) 136 | } 137 | 138 | // AsTime converts the ValueWrapper to a TimeWrapper 139 | func (valWrap ValueWrapper) AsTime() (*TimeWrapper, error) { 140 | if valWrap.value.IsSetTVal() { 141 | rawTime := valWrap.value.GetTVal() 142 | time, err := GenTimeWrapper(rawTime, valWrap.factory, valWrap.timezoneInfo) 143 | if err != nil { 144 | return nil, err 145 | } 146 | return time, nil 147 | } 148 | return nil, fmt.Errorf("failed to convert value %s to Time", valWrap.GetType()) 149 | } 150 | 151 | // AsDate converts the ValueWrapper to a types.Date 152 | func (valWrap ValueWrapper) AsDate() (types.Date, error) { 153 | if valWrap.value.IsSetDVal() { 154 | return valWrap.value.GetDVal(), nil 155 | } 156 | return nil, fmt.Errorf("failed to convert value %s to Date", valWrap.GetType()) 157 | } 158 | 159 | // AsDateTime converts the ValueWrapper to a DateTimeWrapper 160 | func (valWrap ValueWrapper) AsDateTime() (*DateTimeWrapper, error) { 161 | if valWrap.value.IsSetDtVal() { 162 | rawTimeDate := valWrap.value.GetDtVal() 163 | timeDate, err := GenDateTimeWrapper(rawTimeDate, valWrap.factory, valWrap.timezoneInfo) 164 | if err != nil { 165 | return nil, err 166 | } 167 | return timeDate, nil 168 | } 169 | return nil, fmt.Errorf("failed to convert value %s to DateTime", valWrap.GetType()) 170 | } 171 | 172 | // AsList converts the ValueWrapper to a slice of ValueWrapper 173 | func (valWrap ValueWrapper) AsList() ([]ValueWrapper, error) { 174 | if valWrap.value.IsSetLVal() { 175 | var varList []ValueWrapper 176 | vals := valWrap.value.GetLVal().GetValues() 177 | for _, val := range vals { 178 | varList = append(varList, ValueWrapper{val, valWrap.factory, valWrap.timezoneInfo}) 179 | } 180 | return varList, nil 181 | } 182 | return nil, fmt.Errorf("failed to convert value %s to List", valWrap.GetType()) 183 | } 184 | 185 | // AsDedupList converts the ValueWrapper to a slice of ValueWrapper that has unique elements 186 | func (valWrap ValueWrapper) AsDedupList() ([]ValueWrapper, error) { 187 | if valWrap.value.IsSetUVal() { 188 | var varList []ValueWrapper 189 | vals := valWrap.value.GetUVal().GetValues() 190 | for _, val := range vals { 191 | varList = append(varList, ValueWrapper{val, valWrap.factory, valWrap.timezoneInfo}) 192 | } 193 | return varList, nil 194 | } 195 | return nil, fmt.Errorf("failed to convert value %s to set(deduped list)", valWrap.GetType()) 196 | } 197 | 198 | // AsMap converts the ValueWrapper to a map of string and ValueWrapper 199 | func (valWrap ValueWrapper) AsMap() (map[string]ValueWrapper, error) { 200 | if valWrap.value.IsSetMVal() { 201 | newMap := make(map[string]ValueWrapper) 202 | 203 | kvs := valWrap.value.GetMVal().GetKvs() 204 | for key, val := range kvs { 205 | newMap[key] = ValueWrapper{val, valWrap.factory, valWrap.timezoneInfo} 206 | } 207 | return newMap, nil 208 | } 209 | return nil, fmt.Errorf("failed to convert value %s to Map", valWrap.GetType()) 210 | } 211 | 212 | // AsNode converts the ValueWrapper to a Node 213 | func (valWrap ValueWrapper) AsNode() (*Node, error) { 214 | if !valWrap.value.IsSetVVal() { 215 | return nil, fmt.Errorf("failed to convert value %s to Node, value is not an vertex", valWrap.GetType()) 216 | } 217 | vertex := valWrap.value.GetVVal() 218 | node, err := GenNode(vertex, valWrap.factory, valWrap.timezoneInfo) 219 | if err != nil { 220 | return nil, err 221 | } 222 | return node, nil 223 | } 224 | 225 | // AsRelationship converts the ValueWrapper to a Relationship 226 | func (valWrap ValueWrapper) AsRelationship() (*Relationship, error) { 227 | if !valWrap.value.IsSetEVal() { 228 | return nil, fmt.Errorf("failed to convert value %s to Relationship, value is not an edge", valWrap.GetType()) 229 | } 230 | edge := valWrap.value.GetEVal() 231 | relationship, err := GenRelationship(edge, valWrap.factory, valWrap.timezoneInfo) 232 | if err != nil { 233 | return nil, err 234 | } 235 | return relationship, nil 236 | } 237 | 238 | // AsPath converts the ValueWrapper to a PathWrapper 239 | func (valWrap ValueWrapper) AsPath() (*PathWrapper, error) { 240 | if !valWrap.value.IsSetPVal() { 241 | return nil, fmt.Errorf("failed to convert value %s to PathWrapper, value is not an edge", valWrap.GetType()) 242 | } 243 | path, err := GenPathWrapper(valWrap.value.GetPVal(), valWrap.factory, valWrap.timezoneInfo) 244 | if err != nil { 245 | return nil, err 246 | } 247 | return path, nil 248 | } 249 | 250 | // AsPath converts the ValueWrapper to a types.Geography 251 | func (valWrap ValueWrapper) AsGeography() (types.Geography, error) { 252 | if valWrap.value.IsSetGgVal() { 253 | return valWrap.value.GetGgVal(), nil 254 | } 255 | return nil, fmt.Errorf("failed to convert value %s to types.Geography, value is not an geography", valWrap.GetType()) 256 | } 257 | 258 | // AsDuration converts the ValueWrapper to a DurationWrapper 259 | func (valWrap ValueWrapper) AsDuration() (types.Duration, error) { 260 | if valWrap.value.IsSetDuVal() { 261 | rawDuration := valWrap.value.GetDuVal() 262 | return rawDuration, nil 263 | } 264 | return nil, fmt.Errorf("failed to convert value %s to Duration", valWrap.GetType()) 265 | } 266 | 267 | // GetType returns the value type of value in the valWrap as a string 268 | func (valWrap ValueWrapper) GetType() string { 269 | if valWrap.value.IsSetNVal() { 270 | return "null" 271 | } else if valWrap.value.IsSetBVal() { 272 | return "bool" 273 | } else if valWrap.value.IsSetIVal() { 274 | return "int" 275 | } else if valWrap.value.IsSetFVal() { 276 | return "float" 277 | } else if valWrap.value.IsSetSVal() { 278 | return "string" 279 | } else if valWrap.value.IsSetDVal() { 280 | return "date" 281 | } else if valWrap.value.IsSetTVal() { 282 | return "time" 283 | } else if valWrap.value.IsSetDtVal() { 284 | return "datetime" 285 | } else if valWrap.value.IsSetVVal() { 286 | return "vertex" 287 | } else if valWrap.value.IsSetEVal() { 288 | return "edge" 289 | } else if valWrap.value.IsSetPVal() { 290 | return "path" 291 | } else if valWrap.value.IsSetLVal() { 292 | return "list" 293 | } else if valWrap.value.IsSetMVal() { 294 | return "map" 295 | } else if valWrap.value.IsSetUVal() { 296 | return "set" 297 | } else if valWrap.value.IsSetGgVal() { 298 | return "geography" 299 | } else if valWrap.value.IsSetDuVal() { 300 | return "duration" 301 | } 302 | return "empty" 303 | } 304 | 305 | // String() returns the value in the ValueWrapper as a string. 306 | // 307 | // Maps in the output will be sorted by key value in alphabetical order. 308 | // 309 | // For vetex, the output is in form (vid: tagName{propKey: propVal, propKey2, propVal2}), 310 | // For edge, the output is in form (SrcVid)-[name]->(DstVid)@Ranking{prop1: val1, prop2: val2} 311 | // where arrow direction depends on edgeType. 312 | // For path, the output is in form (v1)-[name@edgeRanking]->(v2)-[name@edgeRanking]->(v3) 313 | // 314 | // For time, and dateTime, String returns the value calculated using the timezone offset 315 | // from graph service by default. 316 | func (valWrap ValueWrapper) String() string { 317 | value := valWrap.value 318 | if value.IsSetNVal() { 319 | return value.GetNVal().String() 320 | } else if value.IsSetBVal() { 321 | return fmt.Sprintf("%t", value.GetBVal()) 322 | } else if value.IsSetIVal() { 323 | return fmt.Sprintf("%d", value.GetIVal()) 324 | } else if value.IsSetFVal() { 325 | fStr := strconv.FormatFloat(value.GetFVal(), 'g', -1, 64) 326 | if !strings.Contains(fStr, ".") { 327 | fStr = fStr + ".0" 328 | } 329 | return fStr 330 | } else if value.IsSetSVal() { 331 | return `"` + string(value.GetSVal()) + `"` 332 | } else if value.IsSetDVal() { // Date yyyy-mm-dd 333 | date := value.GetDVal() 334 | dateWrapper, _ := GenDateWrapper(date, valWrap.factory, valWrap.timezoneInfo) 335 | return fmt.Sprintf("%04d-%02d-%02d", 336 | dateWrapper.getYear(), 337 | dateWrapper.getMonth(), 338 | dateWrapper.getDay()) 339 | } else if value.IsSetTVal() { // Time HH:MM:SS.MSMSMS 340 | rawTime := value.GetTVal() 341 | time, _ := GenTimeWrapper(rawTime, valWrap.factory, valWrap.timezoneInfo) 342 | localTime, _ := time.getLocalTime() 343 | return fmt.Sprintf("%02d:%02d:%02d.%06d", 344 | localTime.GetHour(), 345 | localTime.GetMinute(), 346 | localTime.GetSec(), 347 | localTime.GetMicrosec()) 348 | } else if value.IsSetDtVal() { // DateTime yyyy-mm-ddTHH:MM:SS.MSMSMS 349 | rawDateTime := value.GetDtVal() 350 | dateTime, _ := GenDateTimeWrapper(rawDateTime, valWrap.factory, valWrap.timezoneInfo) 351 | localDateTime, _ := dateTime.getLocalDateTime() 352 | return fmt.Sprintf("%d-%02d-%02dT%02d:%02d:%02d.%06d", 353 | localDateTime.GetYear(), 354 | localDateTime.GetMonth(), 355 | localDateTime.GetDay(), 356 | localDateTime.GetHour(), 357 | localDateTime.GetMinute(), 358 | localDateTime.GetSec(), 359 | localDateTime.GetMicrosec()) 360 | } else if value.IsSetVVal() { // Vertex format: ("VertexID" :tag1{k0: v0,k1: v1}:tag2{k2: v2}) 361 | vertex := value.GetVVal() 362 | node, _ := GenNode(vertex, valWrap.factory, valWrap.timezoneInfo) 363 | return node.String() 364 | } else if value.IsSetEVal() { // Edge format: [:edge src->dst @ranking {propKey1: propVal1}] 365 | edge := value.GetEVal() 366 | relationship, _ := GenRelationship(edge, valWrap.factory, valWrap.timezoneInfo) 367 | return relationship.String() 368 | } else if value.IsSetPVal() { 369 | // Path format: 370 | // ("VertexID" :tag1{k0: v0,k1: v1})- 371 | // [:TypeName@ranking {propKey1: propVal1}]-> 372 | // ("VertexID2" :tag1{k0: v0,k1: v1} :tag2{k2: v2})- 373 | // [:TypeName@ranking {propKey2: propVal2}]-> 374 | // ("VertexID3" :tag1{k0: v0,k1: v1}) 375 | path := value.GetPVal() 376 | pathWrap, _ := GenPathWrapper(path, valWrap.factory, valWrap.timezoneInfo) 377 | return pathWrap.String() 378 | } else if value.IsSetLVal() { // List 379 | lval := value.GetLVal() 380 | var strs []string 381 | for _, val := range lval.GetValues() { 382 | strs = append(strs, ValueWrapper{val, valWrap.factory, valWrap.timezoneInfo}.String()) 383 | } 384 | return fmt.Sprintf("[%s]", strings.Join(strs, ", ")) 385 | } else if value.IsSetMVal() { // Map 386 | // {k0: v0, k1: v1} 387 | mval := value.GetMVal() 388 | var keyList []string 389 | var output []string 390 | kvs := mval.GetKvs() 391 | for k := range kvs { 392 | keyList = append(keyList, k) 393 | } 394 | sort.Strings(keyList) 395 | for _, k := range keyList { 396 | output = append(output, fmt.Sprintf("%s: %s", k, ValueWrapper{kvs[k], valWrap.factory, valWrap.timezoneInfo}.String())) 397 | } 398 | return fmt.Sprintf("{%s}", strings.Join(output, ", ")) 399 | } else if value.IsSetUVal() { 400 | // set to string 401 | uval := value.GetUVal() 402 | var strs []string 403 | for _, val := range uval.GetValues() { 404 | strs = append(strs, ValueWrapper{val, valWrap.factory, valWrap.timezoneInfo}.String()) 405 | } 406 | return fmt.Sprintf("{%s}", strings.Join(strs, ", ")) 407 | } else if value.IsSetGgVal() { 408 | ggval := value.GetGgVal() 409 | return toWKT(ggval) 410 | } else if value.IsSetDuVal() { 411 | duval := value.GetDuVal() 412 | days := duval.GetSeconds() / (24 * 60 * 60) 413 | return fmt.Sprintf("P%vM%vDT%vS", duval.GetMonths(), days, duval.GetSeconds()) 414 | } else { // is empty 415 | return "" 416 | } 417 | } 418 | 419 | func toWKT(geo types.Geography) string { 420 | if geo == nil { 421 | return "" 422 | } 423 | if geo.IsSetPtVal() { 424 | ptVal := geo.GetPtVal() 425 | coord := ptVal.GetCoord() 426 | return fmt.Sprintf("POINT(%v %v)", coord.GetX(), coord.GetY()) 427 | } else if geo.IsSetLsVal() { 428 | lsVal := geo.GetLsVal() 429 | coordList := lsVal.GetCoordList() 430 | wkt := "LINESTRING(" 431 | for i, coord := range coordList { 432 | wkt += fmt.Sprintf("%v %v", coord.GetX(), coord.GetY()) 433 | if i != len(coordList)-1 { 434 | wkt += ", " 435 | } 436 | } 437 | wkt += ")" 438 | return wkt 439 | } else if geo.IsSetPgVal() { 440 | pgVal := geo.GetPgVal() 441 | coordListList := pgVal.GetCoordListList() 442 | wkt := "POLYGON(" 443 | for i, coordList := range coordListList { 444 | wkt += "(" 445 | for j, coord := range coordList { 446 | wkt += fmt.Sprintf("%v %v", coord.GetX(), coord.GetY()) 447 | if j != len(coordList)-1 { 448 | wkt += ", " 449 | } 450 | } 451 | wkt += ")" 452 | if i != len(coordListList)-1 { 453 | wkt += ", " 454 | } 455 | } 456 | wkt += ")" 457 | 458 | return wkt 459 | } 460 | return "" 461 | } 462 | -------------------------------------------------------------------------------- /ccore/nebula/wrapper/wrapper.go: -------------------------------------------------------------------------------- 1 | package wrapper 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 8 | ) 9 | 10 | // construct time.Time to types.Time 11 | func WrapTime(localTime time.Time, factory types.FactoryDriver) types.Time { 12 | tb := factory.NewTimeBuilder() 13 | t := tb.Build() 14 | t.SetHour(int8(localTime.Hour())) 15 | t.SetMinute(int8(localTime.Minute())) 16 | t.SetSec(int8(localTime.Second())) 17 | t.SetMicrosec(int32(localTime.Nanosecond() / 1000)) 18 | 19 | return t 20 | } 21 | 22 | // construct time.Time to types.DateTime 23 | func WrapDateTime(localDT time.Time, factory types.FactoryDriver) types.DateTime { 24 | dtb := factory.NewDateTimeBuilder() 25 | datetime := dtb.Build() 26 | datetime.SetYear(int16(localDT.Year())) 27 | datetime.SetMonth(int8(localDT.Month())) 28 | datetime.SetDay(int8(localDT.Day())) 29 | datetime.SetHour(int8(localDT.Hour())) 30 | datetime.SetMinute(int8(localDT.Minute())) 31 | datetime.SetSec(int8(localDT.Second())) 32 | datetime.SetMicrosec(int32(localDT.Nanosecond() / 1000)) 33 | 34 | return datetime 35 | } 36 | 37 | // construct go-type to types.Value 38 | func WrapValue(any interface{}, factory types.FactoryDriver) (types.Value, error) { 39 | var err error 40 | valueBuilder := factory.NewValueBuilder() 41 | value := valueBuilder.Build() 42 | if v, ok := any.(bool); ok { 43 | value.SetBVal(&v) 44 | } else if v, ok := any.(int); ok { 45 | ival := int64(v) 46 | value.SetIVal(&ival) 47 | } else if v, ok := any.(float64); ok { 48 | if v == float64(int64(v)) { 49 | iv := int64(v) 50 | value.SetIVal(&iv) 51 | } else { 52 | value.SetFVal(&v) 53 | } 54 | } else if v, ok := any.(float32); ok { 55 | if v == float32(int64(v)) { 56 | iv := int64(v) 57 | value.SetIVal(&iv) 58 | } else { 59 | fval := float64(v) 60 | value.SetFVal(&fval) 61 | } 62 | } else if v, ok := any.(string); ok { 63 | value.SetSVal([]byte(v)) 64 | } else if any == nil { 65 | nval := types.NullType___NULL__ 66 | value.SetNVal(&nval) 67 | } else if v, ok := any.([]interface{}); ok { 68 | nv, er := Slice2Nlist([]interface{}(v), factory) 69 | if er != nil { 70 | err = er 71 | } 72 | value.SetLVal(nv) 73 | } else if v, ok := any.(map[string]interface{}); ok { 74 | nv, er := Map2Nmap(v, factory) 75 | if er != nil { 76 | err = er 77 | } 78 | value.SetMVal(nv) 79 | } else if v, ok := any.(types.Value); ok { 80 | value = v 81 | } else if v, ok := any.(types.Date); ok { 82 | value.SetDVal(v) 83 | } else if v, ok := any.(types.DateTime); ok { 84 | value.SetDtVal(v) 85 | } else if v, ok := any.(types.Duration); ok { 86 | value.SetDuVal(v) 87 | } else if v, ok := any.(types.Time); ok { 88 | value.SetTVal(v) 89 | } else if v, ok := any.(types.Geography); ok { 90 | value.SetGgVal(v) 91 | } else { 92 | // unsupport other Value type, use this function carefully 93 | err = fmt.Errorf("Only support convert boolean/float/int/string/map/list to nebula.Value but %T", any) 94 | } 95 | return value, err 96 | } 97 | 98 | // construct Slice to types.NList 99 | func Slice2Nlist(list []interface{}, factory types.FactoryDriver) (types.NList, error) { 100 | sv := make([]types.Value, 0, len(list)) 101 | nListBuilder := factory.NewNListBuilder() 102 | for _, item := range list { 103 | nv, er := WrapValue(item, factory) 104 | if er != nil { 105 | return nil, er 106 | } 107 | sv = append(sv, nv) 108 | } 109 | nListBuilder.Values(sv) 110 | return nListBuilder.Build(), nil 111 | } 112 | 113 | // construct map to types.NMap 114 | func Map2Nmap(m map[string]interface{}, factory types.FactoryDriver) (types.NMap, error) { 115 | nMapBuilder := factory.NewNMapBuilder() 116 | kvs := map[string]types.Value{} 117 | for k, v := range m { 118 | nv, err := WrapValue(v, factory) 119 | if err != nil { 120 | return nil, err 121 | } 122 | kvs[k] = nv 123 | } 124 | nMapBuilder.Kvs(kvs) 125 | return nMapBuilder.Build(), nil 126 | } 127 | -------------------------------------------------------------------------------- /common/runtime.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "net/http" 5 | "runtime" 6 | 7 | "github.com/astaxie/beego/logs" 8 | ) 9 | 10 | func LogPanic(r interface{}) { 11 | if r == http.ErrAbortHandler { 12 | return 13 | } 14 | 15 | // Same as stdlib http server code. Manually allocate stack trace buffer size 16 | // to prevent excessively large logs 17 | const size = 64 << 10 18 | stacktrace := make([]byte, size) 19 | stacktrace = stacktrace[:runtime.Stack(stacktrace, false)] 20 | if _, ok := r.(string); ok { 21 | logs.Warn("Observed a panic: %s\n%s", r, stacktrace) 22 | } else { 23 | logs.Warn("Observed a panic: %#v (%v)\n%s", r, r, stacktrace) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /common/tools.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "os" 6 | "path" 7 | "path/filepath" 8 | "strconv" 9 | "syscall" 10 | ) 11 | 12 | func CreateFileWithPerm(filePath string, permCode string) (*os.File, error) { 13 | 14 | if abs := filepath.IsAbs(filePath); !abs { 15 | return nil, errors.New("file path should be absolute path") 16 | } 17 | 18 | perm, err := strconv.ParseInt(permCode, 8, 64) 19 | if err != nil { 20 | return nil, err 21 | } 22 | mask := syscall.Umask(0) 23 | defer syscall.Umask(mask) 24 | filedir := path.Dir(filePath) 25 | os.MkdirAll(filedir, os.FileMode(perm)) 26 | fd, err := os.OpenFile(filePath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(perm)) 27 | defer fd.Close() 28 | if os.IsExist(err) { 29 | os.Chmod(filePath, os.FileMode(perm)) 30 | } 31 | return fd, err 32 | } 33 | -------------------------------------------------------------------------------- /conf/app.conf: -------------------------------------------------------------------------------- 1 | appname = nebula-http-gateway 2 | httpport = 8080 3 | httpaddr = 0.0.0.0 4 | runmode = dev 5 | autorender = false 6 | copyrequestbody = true 7 | logspath = "./logs/" 8 | loglevel = "info" 9 | uploadspath = "./uploads/" 10 | sqlitedbfilepath = "./tasks.db" 11 | sessionkey = "common-nsid" 12 | -------------------------------------------------------------------------------- /controllers/db.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/astaxie/beego" 7 | "github.com/astaxie/beego/logs" 8 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/gateway/dao" 9 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/gateway/pool" 10 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/types" 11 | "github.com/vesoft-inc/nebula-http-gateway/common" 12 | ) 13 | 14 | type DatabaseController struct { 15 | beego.Controller 16 | } 17 | 18 | type Response struct { 19 | Code int `json:"code"` 20 | Data types.Any `json:"data"` 21 | Message string `json:"message"` 22 | } 23 | 24 | type Request struct { 25 | Username string `json:"username"` 26 | Password string `json:"password"` 27 | Address string `json:"address"` 28 | Port int `json:"port"` 29 | 30 | /* 31 | if the request version field is "", 32 | will use `types.VersionHelper()` to infer a version 33 | */ 34 | Version string `json:"version"` 35 | } 36 | 37 | type ExecuteRequest struct { 38 | Gql string `json:"gql"` 39 | ParamList types.ParameterList `json:"paramList"` 40 | } 41 | 42 | type Data map[string]interface{} 43 | 44 | func (this *DatabaseController) Connect() { 45 | var ( 46 | res Response 47 | params Request 48 | ) 49 | json.Unmarshal(this.Ctx.Input.RequestBody, ¶ms) 50 | 51 | info, err := dao.Connect(params.Address, params.Port, params.Username, params.Password) 52 | if err == nil { 53 | nsid := info.ClientID 54 | res.Code = 0 55 | m := make(map[string]types.Any) 56 | m["nsid"] = nsid 57 | res.Data = nsid 58 | this.Ctx.SetCookie("Secure", "true") 59 | this.Ctx.SetCookie("SameSite", "Strict") 60 | this.SetSession(beego.AppConfig.String("sessionkey"), nsid) 61 | 62 | res.Message = "Login successfully" 63 | } else { 64 | res.Code = -1 65 | res.Message = err.Error() 66 | } 67 | 68 | this.Data["json"] = &res 69 | this.ServeJSON() 70 | } 71 | 72 | func (this *DatabaseController) Home() { 73 | var res Response 74 | res.Code = 0 75 | res.Data = "Run Successfully!" 76 | res.Message = "Welcome to nebula http gateway!" 77 | this.Data["json"] = &res 78 | this.ServeJSON() 79 | } 80 | 81 | func (this *DatabaseController) Disconnect() { 82 | var res Response 83 | nsid := this.GetSession(beego.AppConfig.String("sessionkey")) 84 | if nsid == nil { 85 | res.Code = -1 86 | res.Message = "No connection existed" 87 | } else { 88 | err := dao.Disconnect(nsid.(string)) 89 | if err != nil { 90 | res.Code = -1 91 | res.Message = "Disconnect failed" 92 | } else { 93 | res.Code = 0 94 | res.Message = "Disconnect successfully" 95 | } 96 | } 97 | 98 | this.Data["json"] = &res 99 | this.ServeJSON() 100 | } 101 | 102 | func (this *DatabaseController) Execute() { 103 | var res Response 104 | var params ExecuteRequest 105 | nsid := this.GetSession(beego.AppConfig.String("sessionkey")) 106 | if nsid == nil { 107 | res.Code = -1 108 | res.Message = "connection refused for lack of session" 109 | } else { 110 | json.Unmarshal(this.Ctx.Input.RequestBody, ¶ms) 111 | result, msg, err := dao.Execute(nsid.(string), params.Gql, params.ParamList) 112 | if msg != nil { 113 | if err == pool.SessionLostError { 114 | common.LogPanic(msg) 115 | } else { 116 | logs.Error(msg) 117 | } 118 | } 119 | 120 | if err == nil { 121 | res.Code = 0 122 | res.Data = &result 123 | } else { 124 | res.Code = -1 125 | res.Message = err.Error() 126 | } 127 | } 128 | this.Data["json"] = &res 129 | this.ServeJSON() 130 | } 131 | -------------------------------------------------------------------------------- /controllers/db_test.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "io/ioutil" 7 | "log" 8 | "net/http" 9 | "testing" 10 | ) 11 | 12 | func TestDBConnect(t *testing.T) { 13 | var Response Response 14 | cases := []struct { 15 | path string 16 | requestMethod string 17 | requestBody []byte 18 | }{ 19 | { 20 | "http://127.0.0.1:8080/api/db/connect", 21 | "POST", 22 | []byte(`{"username": "root", 23 | "password": "nebula", 24 | "host": "127.0.0.1:9669"}`), 25 | }, 26 | { 27 | "http://127.0.0.1:8080/api/db/connect", 28 | "POST", 29 | []byte(`{"username": "user1", 30 | "password": "password", 31 | "host": "127.0.0.1:9669"}`), 32 | }, 33 | } 34 | 35 | for _, tc := range cases { 36 | req, err := http.NewRequest(tc.requestMethod, tc.path, bytes.NewBuffer(tc.requestBody)) 37 | if err != nil { 38 | t.Fail() 39 | } 40 | req.Header.Set("Content-Type", "application/json") 41 | 42 | client := &http.Client{} 43 | resp, err := client.Do(req) 44 | if err != nil { 45 | t.Fail() 46 | } 47 | 48 | defer req.Body.Close() 49 | body, err := ioutil.ReadAll(resp.Body) 50 | if err != nil { 51 | t.Fail() 52 | } 53 | 54 | if err := json.Unmarshal([]byte(body), &Response); err != nil { 55 | t.Fail() 56 | } 57 | 58 | if Response.Code != -1 && Response.Code != 0 { 59 | t.Fail() 60 | } 61 | } 62 | } 63 | 64 | func TestDBExecute(t *testing.T) { 65 | cases := []struct { 66 | path string 67 | requestMethod string 68 | requestBody []byte 69 | }{ 70 | { 71 | "http://127.0.0.1:8080/api/db/exec", 72 | "POST", 73 | []byte(`{"username" : "user", 74 | "password" : "password", 75 | "host" : "127.0.0.1:9669", 76 | "gql" : "SHOW SPACES11;"}`), 77 | }, 78 | } 79 | for _, tc := range cases { 80 | var Response Response 81 | req, err := http.NewRequest(tc.requestMethod, tc.path, bytes.NewBuffer(tc.requestBody)) 82 | if err != nil { 83 | t.Fail() 84 | } 85 | req.Header.Set("Content-Type", "application/json") 86 | 87 | client := &http.Client{} 88 | resp, err := client.Do(req) 89 | 90 | if err != nil { 91 | log.Fatal(err) 92 | } 93 | 94 | defer resp.Body.Close() 95 | 96 | body, err := ioutil.ReadAll(resp.Body) 97 | if err != nil { 98 | t.Fail() 99 | } 100 | 101 | if err := json.Unmarshal([]byte(body), &Response); err != nil { 102 | t.Fail() 103 | } 104 | 105 | if Response.Code != -1 && Response.Code != 0 { 106 | t.Fail() 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /controllers/task.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/astaxie/beego" 8 | "github.com/astaxie/beego/logs" 9 | "github.com/vesoft-inc/nebula-http-gateway/service/importer" 10 | "github.com/vesoft-inc/nebula-importer/pkg/config" 11 | 12 | importerErrors "github.com/vesoft-inc/nebula-importer/pkg/errors" 13 | ) 14 | 15 | type TaskController struct { 16 | beego.Controller 17 | } 18 | 19 | type ImportRequest struct { 20 | ConfigPath string `json:"configPath"` 21 | ConfigBody config.YAMLConfig `json:"configBody"` 22 | } 23 | 24 | type ImportActionRequest struct { 25 | TaskID string `json:"taskID"` 26 | TaskAction string `json:"taskAction"` 27 | } 28 | 29 | func (this *TaskController) Import() { 30 | var ( 31 | res Response 32 | params ImportRequest 33 | taskID string = importer.NewTaskID() 34 | err error 35 | ) 36 | 37 | task := importer.NewTask(taskID) 38 | importer.GetTaskMgr().PutTask(taskID, &task) 39 | 40 | err = json.Unmarshal(this.Ctx.Input.RequestBody, ¶ms) 41 | 42 | if err != nil { 43 | err = importerErrors.Wrap(importerErrors.InvalidConfigPathOrFormat, err) 44 | } else { 45 | err = importer.Import(taskID, params.ConfigPath, ¶ms.ConfigBody) 46 | } 47 | 48 | if err != nil { 49 | // task err: import task not start err handle 50 | task.TaskStatus = importer.StatusAborted.String() 51 | logs.Error(fmt.Sprintf("Failed to start a import task: `%s`, task result: `%v`", taskID, err)) 52 | 53 | res.Code = -1 54 | res.Message = err.Error() 55 | } else { 56 | res.Code = 0 57 | res.Data = []string{taskID} 58 | res.Message = fmt.Sprintf("Import task %s submit successfully", taskID) 59 | } 60 | this.Data["json"] = &res 61 | this.ServeJSON() 62 | } 63 | 64 | func (this *TaskController) ImportAction() { 65 | var res Response 66 | var params ImportActionRequest 67 | 68 | json.Unmarshal(this.Ctx.Input.RequestBody, ¶ms) 69 | result, err := importer.ImportAction(params.TaskID, importer.NewTaskAction(params.TaskAction)) 70 | if err == nil { 71 | res.Code = 0 72 | res.Data = result 73 | res.Message = "Processing a task action successfully" 74 | } else { 75 | res.Code = -1 76 | res.Message = err.Error() 77 | } 78 | this.Data["json"] = &res 79 | this.ServeJSON() 80 | } 81 | -------------------------------------------------------------------------------- /controllers/task_test.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "io/ioutil" 7 | "log" 8 | "net/http" 9 | "testing" 10 | ) 11 | 12 | func Test_Task_Import(t *testing.T) { 13 | /* 14 | */ 15 | cases := []struct { 16 | path string 17 | requestMethod string 18 | requestBody []byte 19 | }{ 20 | { 21 | "http://127.0.0.1:8080/api/task/import", 22 | "POST", 23 | []byte(`{"configPath" : "examples/v2/example.yaml"}`), 24 | }, 25 | } 26 | for _, tc := range cases { 27 | var Response Response 28 | req, err := http.NewRequest(tc.requestMethod, tc.path, bytes.NewBuffer(tc.requestBody)) 29 | req.Header.Set("Content-Type", "application/json") 30 | 31 | if err != nil { 32 | log.Fatal(err) 33 | } 34 | 35 | client := &http.Client{} 36 | resp, err := client.Do(req) 37 | 38 | if err != nil { 39 | log.Fatal(err) 40 | } 41 | 42 | defer resp.Body.Close() 43 | 44 | body, _ := ioutil.ReadAll(resp.Body) 45 | 46 | json.Unmarshal([]byte(body), &Response) 47 | if Response.Code != -1 && Response.Code != 0 { 48 | t.Fail() 49 | } 50 | } 51 | } 52 | 53 | func Test_Task_Action(t *testing.T) { 54 | /* 55 | */ 56 | cases := []struct { 57 | path string 58 | requestMethod string 59 | requestBody []byte 60 | }{ 61 | { 62 | "http://127.0.0.1:8080/api/task/action", 63 | "POST", 64 | []byte(`{"taskID" : "0", "taskAction": "stop"}`), 65 | }, 66 | { 67 | "http://127.0.0.1:8080/api/task/action", 68 | "POST", 69 | []byte(`{"taskAction": "stopAll"}`), 70 | }, 71 | { 72 | "http://127.0.0.1:8080/api/task/action", 73 | "POST", 74 | []byte(`{"taskID" : "0", "taskAction": "query"}`), 75 | }, 76 | { 77 | "http://127.0.0.1:8080/api/task/action", 78 | "POST", 79 | []byte(`{"taskAction": "queryAll"}`), 80 | }, 81 | } 82 | for _, tc := range cases { 83 | var Response Response 84 | req, err := http.NewRequest(tc.requestMethod, tc.path, bytes.NewBuffer(tc.requestBody)) 85 | req.Header.Set("Content-Type", "application/json") 86 | 87 | if err != nil { 88 | log.Fatal(err) 89 | } 90 | 91 | client := &http.Client{} 92 | resp, err := client.Do(req) 93 | 94 | if err != nil { 95 | log.Fatal(err) 96 | } 97 | 98 | defer resp.Body.Close() 99 | 100 | body, _ := ioutil.ReadAll(resp.Body) 101 | 102 | json.Unmarshal([]byte(body), &Response) 103 | if Response.Code != -1 && Response.Code != 0 { 104 | t.Fail() 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/vesoft-inc/nebula-http-gateway 2 | 3 | go 1.13 4 | 5 | replace github.com/vesoft-inc/nebula-http-gateway/ccore v0.0.0 => ./ccore 6 | 7 | require ( 8 | github.com/astaxie/beego v1.12.3 9 | github.com/mattn/go-sqlite3 v2.0.3+incompatible 10 | github.com/vesoft-inc/nebula-http-gateway/ccore v0.0.0 11 | github.com/vesoft-inc/nebula-importer v1.0.1-0.20220719030708-8e376665042e 12 | ) 13 | 14 | require ( 15 | github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect 16 | github.com/google/go-cmp v0.5.4 // indirect 17 | github.com/prometheus/client_golang v1.9.0 // indirect 18 | github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect 19 | github.com/vesoft-inc/nebula-go/v3 v3.4.0 // indirect 20 | golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect 21 | golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect 22 | golang.org/x/sys v0.0.0-20210105210732-16f7687f5001 // indirect 23 | golang.org/x/text v0.3.4 // indirect 24 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect 25 | google.golang.org/protobuf v1.25.0 // indirect 26 | gopkg.in/yaml.v2 v2.4.0 // indirect 27 | ) 28 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "os" 8 | "os/signal" 9 | "path/filepath" 10 | "syscall" 11 | "time" 12 | 13 | "github.com/astaxie/beego" 14 | "github.com/astaxie/beego/logs" 15 | "github.com/vesoft-inc/nebula-http-gateway/common" 16 | _ "github.com/vesoft-inc/nebula-http-gateway/routers" 17 | 18 | "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/gateway/pool" 19 | ) 20 | 21 | func main() { 22 | 23 | /* 24 | session config 25 | */ 26 | beego.BConfig.WebConfig.Session.SessionCookieLifeTime = 0 27 | beego.BConfig.WebConfig.Session.SessionGCMaxLifetime = 60 * 60 * 24 28 | beego.BConfig.WebConfig.Session.SessionName = beego.AppConfig.String("sessionkey") 29 | beego.BConfig.WebConfig.Session.SessionOn = true 30 | 31 | /* 32 | logger config 33 | */ 34 | logsPath := beego.AppConfig.DefaultString("logspath", "./logs/") 35 | absLogsPath, _ := filepath.Abs(logsPath) 36 | _, err := common.CreateFileWithPerm(absLogsPath+"/", "0720") 37 | 38 | if err != nil && os.IsNotExist(err) { 39 | log.Fatalf("create file %s with error: %s", absLogsPath, err.Error()) 40 | } 41 | 42 | logFileName := beego.AppConfig.DefaultString("appname", "nebula-http-gateway") 43 | logFileName += ".log" 44 | 45 | logFilePath := filepath.Join( 46 | absLogsPath, 47 | logFileName, 48 | ) 49 | 50 | logLevelString := beego.AppConfig.String("logLevel") 51 | logLevel := logs.LevelWarning 52 | switch logLevelString { 53 | case "error": 54 | logLevel = logs.LevelError 55 | case "warning", "warn": 56 | logLevel = logs.LevelWarning 57 | case "notice": 58 | logLevel = logs.LevelNotice 59 | case "informational", "info": 60 | logLevel = logs.LevelInformational 61 | case "debug": 62 | logLevel = logs.LevelDebug 63 | } 64 | 65 | logs.SetLogger("file", fmt.Sprintf(`{"filename":"%s","MaxSize":104857600,"perm":"0620"}`, logFilePath)) 66 | logs.GetBeeLogger().DelLogger("console") 67 | logs.SetLogFuncCall(true) 68 | logs.SetLogFuncCallDepth(3) 69 | logs.SetLevel(logLevel) 70 | defer func() { 71 | logs.GetBeeLogger().Flush() 72 | }() 73 | 74 | /* 75 | importer file uploads config 76 | */ 77 | uploadsPath := beego.AppConfig.String("uploadspath") 78 | absUploadsPath, _ := filepath.Abs(uploadsPath) 79 | _, err = common.CreateFileWithPerm(absUploadsPath+"/", "0720") 80 | 81 | if err != nil && os.IsNotExist(err) { 82 | log.Fatalf("create file %s with error: %s", absLogsPath, err.Error()) 83 | } 84 | 85 | /* 86 | use channel to wait server quit. 87 | */ 88 | done := make(chan bool, 1) 89 | quit := make(chan os.Signal, 1) 90 | signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) 91 | if !signal.Ignored(syscall.SIGHUP) { 92 | signal.Notify(quit, syscall.SIGHUP) 93 | } 94 | 95 | go func() { 96 | <-quit 97 | 98 | logs.Info("server is shutting down") 99 | 100 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) 101 | defer cancel() 102 | pool.ClearClients() 103 | beego.BeeApp.Server.SetKeepAlivesEnabled(false) 104 | if err := beego.BeeApp.Server.Shutdown(ctx); err != nil { 105 | logs.Error(err.Error()) 106 | } 107 | 108 | close(done) 109 | }() 110 | 111 | beego.Run() 112 | 113 | <-done 114 | logs.Info("server closed") 115 | } 116 | -------------------------------------------------------------------------------- /routers/router.go: -------------------------------------------------------------------------------- 1 | package routers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | "github.com/vesoft-inc/nebula-http-gateway/controllers" 6 | ) 7 | 8 | func init() { 9 | beego.Router("/", &controllers.DatabaseController{}, "*:Home") 10 | beego.Router("/api/db/connect", &controllers.DatabaseController{}, "POST:Connect") 11 | beego.Router("/api/db/exec", &controllers.DatabaseController{}, "POST:Execute") 12 | beego.Router("/api/db/disconnect", &controllers.DatabaseController{}, "POST:Disconnect") 13 | 14 | beego.Router("/api/task/import", &controllers.TaskController{}, "POST:Import") 15 | beego.Router("/api/task/import/action", &controllers.TaskController{}, "POST:ImportAction") 16 | } 17 | -------------------------------------------------------------------------------- /service/importer/importer.go: -------------------------------------------------------------------------------- 1 | package importer 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "path/filepath" 7 | "time" 8 | 9 | "github.com/vesoft-inc/nebula-importer/pkg/logger" 10 | 11 | "github.com/astaxie/beego" 12 | "github.com/astaxie/beego/logs" 13 | "github.com/vesoft-inc/nebula-importer/pkg/config" 14 | importerErrors "github.com/vesoft-inc/nebula-importer/pkg/errors" 15 | ) 16 | 17 | type ImportResult struct { 18 | TaskId string `json:"taskId"` 19 | TimeCost string `json:"timeCost"` // Milliseconds 20 | FailedRows int64 `json:"failedRows"` 21 | ErrorResult struct { 22 | ErrorCode int `json:"errorCode"` 23 | ErrorMsg string `json:"errorMsg"` 24 | } 25 | } 26 | 27 | type ActionResult struct { 28 | Results []Task `json:"results"` 29 | Msg string `json:"msg"` 30 | } 31 | 32 | func Import(taskID string, configPath string, configBody *config.YAMLConfig) (err error) { 33 | 34 | logs.Debug(fmt.Sprintf("Start a import task: `%s`", taskID)) 35 | 36 | var conf *config.YAMLConfig 37 | 38 | var logPath string 39 | if configBody.LogPath == nil { 40 | logPath = "" 41 | } else { 42 | logPath = *configBody.LogPath 43 | } 44 | runnerLogger := logger.NewRunnerLogger(logPath) 45 | if configPath != "" { 46 | conf, err = config.Parse( 47 | filepath.Join( 48 | beego.AppConfig.String("uploadspath"), 49 | configPath, 50 | ), runnerLogger, 51 | ) 52 | 53 | if err != nil { 54 | logs.Error(err.(importerErrors.ImporterError)) 55 | return err.(importerErrors.ImporterError) 56 | } 57 | } else { 58 | conf = configBody 59 | } 60 | 61 | if err := conf.ValidateAndReset("", runnerLogger); err != nil { 62 | return err 63 | } 64 | 65 | task, _ := GetTaskMgr().GetTask(taskID) 66 | 67 | go func() { 68 | result := ImportResult{} 69 | 70 | now := time.Now() 71 | task.GetRunner().Run(conf) 72 | timeCost := time.Since(now).Milliseconds() 73 | 74 | result.TaskId = taskID 75 | result.TimeCost = fmt.Sprintf("%dms", timeCost) 76 | 77 | if rerr := task.GetRunner().Error(); rerr != nil { 78 | // task err: import task not finished err handle 79 | task.TaskStatus = StatusAborted.String() 80 | 81 | err, _ := rerr.(importerErrors.ImporterError) 82 | result.ErrorResult.ErrorCode = err.ErrCode 83 | result.ErrorResult.ErrorMsg = err.ErrMsg.Error() 84 | task.TaskMessage = err.ErrMsg.Error() 85 | logs.Error(fmt.Sprintf("Failed to finish a import task: `%s`, task result: `%v`", taskID, result)) 86 | } else { 87 | task.TaskStatus = StatusFinished.String() 88 | 89 | result.FailedRows = task.GetRunner().NumFailed 90 | GetTaskMgr().DelTask(taskID) 91 | 92 | logs.Debug(fmt.Sprintf("Success to finish a import task: `%s`, task result: `%v`", taskID, result)) 93 | } 94 | }() 95 | return nil 96 | } 97 | 98 | func ImportAction(taskID string, taskAction TaskAction) (result ActionResult, err error) { 99 | logs.Debug(fmt.Sprintf("Start a import task action: `%s` for task: `%s`", taskAction.String(), taskID)) 100 | 101 | result = ActionResult{} 102 | 103 | switch taskAction { 104 | case ActionQuery: 105 | actionQuery(taskID, &result) 106 | case ActionQueryAll: 107 | actionQueryAll(&result) 108 | case ActionStop: 109 | actionStop(taskID, &result) 110 | case ActionStopAll: 111 | actionStopAll(&result) 112 | default: 113 | err = errors.New("unknown task action") 114 | } 115 | 116 | logs.Debug(fmt.Sprintf("The import task action: `%s` for task: `%s` finished, action result: `%v`", taskAction.String(), taskID, result)) 117 | 118 | return result, err 119 | } 120 | 121 | func actionQuery(taskID string, result *ActionResult) { 122 | // a temp task obj for response 123 | task := Task{} 124 | if t, ok := GetTaskMgr().GetTask(taskID); ok { 125 | task.TaskID = t.TaskID 126 | task.TaskStatus = t.TaskStatus 127 | task.TaskMessage = t.TaskMessage 128 | result.Results = append(result.Results, task) 129 | result.Msg = "Task query successfully" 130 | } else { 131 | task.TaskID = taskID 132 | task.TaskStatus = StatusNotExisted.String() 133 | result.Results = append(result.Results, task) 134 | result.Msg = "Task not existed" 135 | } 136 | } 137 | 138 | /* 139 | `actionQueryAll` will return all tasks with status Aborted or Processing 140 | */ 141 | func actionQueryAll(result *ActionResult) { 142 | taskIDs := GetTaskMgr().GetAllTaskIDs() 143 | for _, taskID := range taskIDs { 144 | actionQuery(taskID, result) 145 | } 146 | 147 | result.Msg = "Tasks query successfully" 148 | } 149 | 150 | func actionStop(taskID string, result *ActionResult) { 151 | ok := GetTaskMgr().StopTask(taskID) 152 | 153 | actionQuery(taskID, result) 154 | 155 | if !ok { 156 | result.Msg = "Task has stoped or finished" 157 | } 158 | 159 | result.Msg = "Task stop successfully" 160 | } 161 | 162 | /* 163 | `actionStopAll` will stop all tasks with status Processing 164 | */ 165 | func actionStopAll(result *ActionResult) { 166 | taskIDs := GetTaskMgr().GetAllTaskIDs() 167 | for _, taskID := range taskIDs { 168 | if _task, _ := GetTaskMgr().GetTask(taskID); _task.TaskStatus == StatusProcessing.String() { 169 | actionStop(taskID, result) 170 | } 171 | } 172 | 173 | result.Msg = "Tasks stop successfully" 174 | } 175 | -------------------------------------------------------------------------------- /service/importer/taskmgr.go: -------------------------------------------------------------------------------- 1 | package importer 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "log" 7 | "os" 8 | "strconv" 9 | "sync" 10 | 11 | "github.com/astaxie/beego" 12 | "github.com/astaxie/beego/logs" 13 | _ "github.com/mattn/go-sqlite3" 14 | "github.com/vesoft-inc/nebula-importer/pkg/cmd" 15 | ) 16 | 17 | var ( 18 | taskmgr *TaskMgr = &TaskMgr{ 19 | tasks: sync.Map{}, 20 | db: &sql.DB{}, 21 | } 22 | 23 | tid uint64 = 0 24 | 25 | mux sync.Mutex 26 | ) 27 | 28 | type TaskMgr struct { 29 | tasks sync.Map 30 | db *sql.DB 31 | } 32 | 33 | type Task struct { 34 | runner *cmd.Runner 35 | 36 | TaskID string `json:"taskID"` 37 | TaskStatus string `json:"taskStatus"` 38 | TaskMessage string `json:"taskMessage"` 39 | } 40 | 41 | func init() { 42 | initDB() 43 | } 44 | 45 | func NewTask(taskID string) Task { 46 | return Task{ 47 | runner: &cmd.Runner{}, 48 | TaskID: taskID, 49 | TaskStatus: StatusProcessing.String(), 50 | } 51 | } 52 | 53 | func (task *Task) GetRunner() *cmd.Runner { 54 | return task.runner 55 | } 56 | 57 | func GetTaskID() (_tid uint64) { 58 | mux.Lock() 59 | defer mux.Unlock() 60 | _tid = tid 61 | return _tid 62 | } 63 | 64 | func NewTaskID() (taskID string) { 65 | mux.Lock() 66 | defer mux.Unlock() 67 | tid++ 68 | taskID = fmt.Sprintf("%d", tid) 69 | return taskID 70 | } 71 | 72 | func GetTaskMgr() *TaskMgr { 73 | return taskmgr 74 | } 75 | 76 | /* 77 | `GetTask` get task from map and local sql 78 | */ 79 | func (mgr *TaskMgr) GetTask(taskID string) (*Task, bool) { 80 | _tid, _ := strconv.ParseUint(taskID, 0, 64) 81 | 82 | if _tid > GetTaskID() || tid <= 0 { 83 | return nil, false 84 | } 85 | 86 | if task, ok := mgr.getTaskFromMap(taskID); ok { 87 | return task, true 88 | } 89 | 90 | return mgr.getTaskFromSQL(taskID), true 91 | } 92 | 93 | /* 94 | `PutTask` put task into tasks map 95 | */ 96 | func (mgr *TaskMgr) PutTask(taskID string, task *Task) { 97 | mgr.tasks.Store(taskID, task) 98 | } 99 | 100 | /* 101 | `DelTask` will delete task in the map, 102 | and put the task into local sql 103 | */ 104 | func (mgr *TaskMgr) DelTask(taskID string) { 105 | task, ok := mgr.getTaskFromMap(taskID) 106 | 107 | if !ok { 108 | return 109 | } 110 | 111 | mgr.tasks.Delete(taskID) 112 | mgr.putTaskIntoSQL(taskID, task) 113 | } 114 | 115 | /* 116 | `StopTask` will change the task status to `StatusStoped`, 117 | and then call `DelTask` 118 | */ 119 | func (mgr *TaskMgr) StopTask(taskID string) bool { 120 | if task, ok := mgr.getTaskFromMap(taskID); ok { 121 | for _, r := range task.GetRunner().Readers { 122 | r.Stop() 123 | } 124 | 125 | task.TaskStatus = StatusStoped.String() 126 | 127 | mgr.DelTask(taskID) 128 | 129 | return true 130 | } 131 | 132 | return false 133 | } 134 | 135 | /* 136 | `GetAllTaskIDs` will return all task ids in map 137 | */ 138 | func (mgr *TaskMgr) GetAllTaskIDs() []string { 139 | ids := make([]string, 0) 140 | mgr.tasks.Range(func(k, v interface{}) bool { 141 | ids = append(ids, k.(string)) 142 | return true 143 | }) 144 | 145 | return ids 146 | } 147 | 148 | /* 149 | `initDB` initialize local sql by open sql and create tasks table 150 | */ 151 | func initDB() { 152 | dbFilePath := beego.AppConfig.String("sqlitedbfilepath") 153 | 154 | os.Remove(dbFilePath) 155 | 156 | _db, err := sql.Open("sqlite3", dbFilePath) 157 | 158 | if err != nil { 159 | logs.Emergency(err.Error()) 160 | log.Panic(err) 161 | } 162 | 163 | GetTaskMgr().db = _db 164 | 165 | sqlStmt := ` 166 | create table tasks (taskID integer not null primary key, taskStatus text, taskMessage text); 167 | delete from tasks; 168 | ` 169 | _, err = GetTaskMgr().db.Exec(sqlStmt) 170 | 171 | if err != nil { 172 | logs.Emergency(fmt.Sprintf("%q: %s\n", err, sqlStmt)) 173 | log.Panicf("%q: %s\n", err, sqlStmt) 174 | } 175 | 176 | } 177 | 178 | func (mgr *TaskMgr) getTaskFromMap(taskID string) (*Task, bool) { 179 | if task, ok := mgr.tasks.Load(taskID); ok { 180 | return task.(*Task), true 181 | } 182 | 183 | return nil, false 184 | } 185 | 186 | func (mgr *TaskMgr) getTaskFromSQL(taskID string) *Task { 187 | var taskStatus string 188 | 189 | rows, _ := mgr.db.Query(fmt.Sprintf("SELECT taskStatus FROM tasks WHERE taskID=%s", taskID)) 190 | 191 | for rows.Next() { 192 | _ = rows.Scan(&taskStatus) 193 | } 194 | 195 | return &Task{ 196 | TaskID: taskID, 197 | TaskStatus: taskStatus, 198 | } 199 | } 200 | 201 | func (mgr *TaskMgr) putTaskIntoSQL(taskID string, task *Task) { 202 | stmt, _ := mgr.db.Prepare("INSERT INTO tasks(taskID, taskStatus) values(?,?)") 203 | 204 | _, _ = stmt.Exec(taskID, task.TaskStatus) 205 | } 206 | 207 | type TaskAction int 208 | 209 | const ( 210 | ActionUnknown TaskAction = iota 211 | ActionQuery 212 | ActionQueryAll 213 | ActionStop 214 | ActionStopAll 215 | ) 216 | 217 | var taskActionMap = map[TaskAction]string{ 218 | ActionQuery: "actionQuery", 219 | ActionQueryAll: "actionQueryAll", 220 | ActionStop: "actionStop", 221 | ActionStopAll: "actionStopAll", 222 | } 223 | 224 | var taskActionRevMap = map[string]TaskAction{ 225 | "actionQuery": ActionQuery, 226 | "actionQueryAll": ActionQueryAll, 227 | "actionStop": ActionStop, 228 | "actionStopAll": ActionStopAll, 229 | } 230 | 231 | func NewTaskAction(action string) TaskAction { 232 | if v, ok := taskActionRevMap[action]; ok { 233 | return v 234 | } 235 | return ActionUnknown 236 | } 237 | 238 | func (action TaskAction) String() string { 239 | if v, ok := taskActionMap[action]; ok { 240 | return v 241 | } 242 | return "actionUnknown" 243 | } 244 | 245 | type TaskStatus int 246 | 247 | /* 248 | the task in memory (map) has 2 status: processing, aborted; 249 | and the task in local sql has 2 status: finished, stoped; 250 | */ 251 | const ( 252 | StatusUnknown TaskStatus = iota 253 | StatusFinished 254 | StatusStoped 255 | StatusProcessing 256 | StatusNotExisted 257 | StatusAborted 258 | ) 259 | 260 | var taskStatusMap = map[TaskStatus]string{ 261 | StatusFinished: "statusFinished", 262 | StatusStoped: "statusStoped", 263 | StatusProcessing: "statusProcessing", 264 | StatusNotExisted: "statusNotExisted", 265 | StatusAborted: "statusAborted", 266 | } 267 | 268 | var taskStatusRevMap = map[string]TaskStatus{ 269 | "statusFinished": StatusFinished, 270 | "statusStoped": StatusStoped, 271 | "statusProcessing": StatusProcessing, 272 | "statusNotExisted": StatusNotExisted, 273 | "statusAborted": StatusAborted, 274 | } 275 | 276 | func NewTaskStatus(status string) TaskStatus { 277 | if v, ok := taskStatusRevMap[status]; ok { 278 | return v 279 | } 280 | return StatusUnknown 281 | } 282 | 283 | func (status TaskStatus) String() string { 284 | if v, ok := taskStatusMap[status]; ok { 285 | return v 286 | } 287 | return "statusUnknown" 288 | } 289 | -------------------------------------------------------------------------------- /service/logger/adapter.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/astaxie/beego/logs" 7 | ) 8 | 9 | type HttpGatewayLogger struct{} 10 | 11 | func (l HttpGatewayLogger) Info(msg string) { 12 | logs.Info(fmt.Sprintf("[nebula-clients] %s", msg)) 13 | } 14 | 15 | func (l HttpGatewayLogger) Warn(msg string) { 16 | logs.Warn(fmt.Sprintf("[nebula-clients] %s", msg)) 17 | } 18 | 19 | func (l HttpGatewayLogger) Error(msg string) { 20 | logs.Error(fmt.Sprintf("[nebula-clients] %s", msg)) 21 | } 22 | 23 | func (l HttpGatewayLogger) Fatal(msg string) { 24 | logs.Emergency(fmt.Sprintf("[nebula-clients] %s", msg)) 25 | } 26 | --------------------------------------------------------------------------------