Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
1c0fa1d
first codec generated.
Dec 17, 2020
6ffdf3e
first codec generated.
Dec 18, 2020
1dad2bc
first codec generated.
Dec 21, 2020
5d2f142
first codec generated.
Dec 21, 2020
705d033
first codec generated.
Dec 21, 2020
51d447b
first codec generated.
Dec 21, 2020
5f1a490
first codec generated.
Dec 21, 2020
f815201
first codec generated.
Dec 22, 2020
f3f729a
first codec generated.
Dec 23, 2020
f35fa90
first codec generated.
Dec 27, 2020
53e1d43
Go codec refactoring first state
yuce Feb 24, 2021
985fd84
Go codec refactoring second stage
yuce Feb 24, 2021
abee092
fixed conflicts
yuce Feb 24, 2021
965b588
More Go generator updates
yuce Feb 24, 2021
ae8f640
More Go generator updates
yuce Feb 25, 2021
537081b
More Go generator updates
yuce Feb 25, 2021
afed897
More Go generator updates
yuce Feb 25, 2021
99e5201
- Fix initialFrame in Go templates
yuce Mar 10, 2021
00c427a
Updated Go generator
yuce Mar 16, 2021
1e72881
Enabled more codecs
yuce Mar 20, 2021
1aa3e12
Enabled more codecs
yuce Mar 26, 2021
b62f876
updates
yuce Jul 30, 2021
ab065cb
Merge branch 'master' into refactor-go-generato
yuce Jul 30, 2021
de5fcf4
updates
yuce Sep 22, 2021
6988873
updates
yuce Sep 22, 2021
f44bcf3
updates
yuce Dec 22, 2021
cf9bf47
Merge branch 'master' into refactor-go-generato
yuce Dec 22, 2021
cda20d2
initial Go client extensibility
yuce Feb 15, 2022
0ab1357
Added missing Go generator files
yuce Feb 15, 2022
03065cf
Updates
yuce Feb 16, 2022
3792b43
Updates
yuce Apr 7, 2022
8ed2497
Updates
yuce Apr 7, 2022
745fc57
Added missing type template
yuce Apr 11, 2022
f20d461
Merge branch 'master' into go-client-extensibility
yuce Apr 11, 2022
485f123
codec fix
yuce Apr 11, 2022
d025e67
codec fix
yuce Apr 12, 2022
3f24cfd
trivial
yuce Jul 20, 2022
1e1de9b
Merge branch 'master' into go-client-extensibility
yuce Oct 5, 2022
0ce9c1e
Jet job submission from non-java client [HZ-1455]
orcunc Dec 13, 2022
bfcba28
Jet job submission from non-java client [HZ-1455]
orcunc Dec 16, 2022
211ffe6
Jet job submission from non-java client [HZ-1455]
orcunc Dec 20, 2022
68831d8
Jet job submission from non-java client [HZ-1455]
orcunc Dec 21, 2022
80d56a0
Merged with master
yuce Jan 6, 2023
2193740
Jet job submission from non-java client [HZ-1455]
orcunc Jan 10, 2023
4ded848
Jet job submission from non-java client [HZ-1455]
orcunc Jan 10, 2023
519eb00
Jet job submission from non-java client [HZ-1455]
orcunc Jan 10, 2023
9f232a9
Merge remote-tracking branch 'orcunc/feature/hz-1455_nonjava_client' …
yuce Jan 10, 2023
48861ae
Merge branch 'master' into clc-job-submission
yuce Mar 15, 2023
b61e52b
Merge branch 'master' into go-client-extensibility
yuce Dec 13, 2023
9f5971d
Updates
yuce Mar 7, 2024
69a1d81
Merge branch 'master' into go-client-extensibility
yuce Aug 12, 2024
e542cd2
Added setuptools as a dependency
yuce Aug 12, 2024
c3c8369
Merge branch 'master' into go-client-extensibility
yuce Nov 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

import argparse
import time
from os.path import abspath, dirname, exists, join, realpath
from os.path import abspath, exists

from jinja2 import TemplateNotFound

from binary.util import binary_output_directories, test_output_directories
from binary_generator import get_binary_templates, save_binary_files, save_test_files
from util import *
from go import GoGenerator

start = time.time()

Expand Down Expand Up @@ -119,7 +120,21 @@
"should be performed. These checks are done by default.",
)

parser.add_argument(
"-s",
"--service",
action="append",
help="Specify the service to include. Can be used more than once to add more services.",
)

parser.add_argument(
"--go-config",
help="(Go only) Specifies the Go generator configuration file. Implies '-l go'",
)

args = parser.parse_args()
if args.go_config:
args.lang = "go"

lang = SupportedLanguages[args.lang.upper()]

Expand Down Expand Up @@ -149,20 +164,23 @@

protocol_defs = sorted(protocol_defs, key=lambda proto_def: proto_def["id"])

if not validate_services(
protocol_defs, schema_path, args.no_id_check, protocol_versions_as_numbers
):
exit(-1)

if custom_protocol_defs and not validate_custom_protocol_definitions(
custom_protocol_defs, custom_codec_schema_path, protocol_versions_as_numbers
):
exit(-1)

print("Hazelcast Client Binary Protocol version", protocol_versions[-1])

copy_verbatim_files(codec_output_dir, lang.value)

if lang == SupportedLanguages.GO:
gen = GoGenerator(protocol_defs, custom_protocol_defs, codec_output_dir, args)
gen.generate()
exit(0)

env = create_environment(lang, args.namespace)


if lang != SupportedLanguages.MD:
codec_template = env.get_template("codec-template.%s.j2" % lang.value)
generate_codecs(protocol_defs, custom_protocol_defs, codec_template, codec_output_dir, lang, env)
Expand Down
1 change: 1 addition & 0 deletions go/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .generator import GoGenerator
244 changes: 244 additions & 0 deletions go/codec-template.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
{% macro encode_var_sized(param, loop_last) -%}
{% if is_var_sized_list(param.type) or is_var_sized_list_contains_nullable(param.type) -%}
Encode{% if param.nullable %}Nullable{% endif %}ListMultiFrame{% if is_var_sized_list_contains_nullable(param.type)%}ContainsNullable{% endif %}For{{ item_type(lang_name, param.type) }}(clientMessage, {{ escape_keyword(param.name) }})
{%- elif is_var_sized_entry_list(param.type) -%}
Encode{% if param.nullable %}Nullable{% endif %}EntryListFor{{ key_type(lang_name, param.type) }}And{{ value_type(lang_name, param.type) }}(clientMessage, {{ param_name(param.name) }})
{%- elif is_var_sized_map(param.type) -%}
Encode{% if param.nullable %}Nullable{% endif %}Map(clientMessage, {{ param_name(param.name) }}, Encode{{ key_type(lang_name, param.type) }}, Encode{{ value_type(lang_name, param.type) }}{% if loop_last %}, True{% endif %})
{%- else -%}
{%- if param.nullable -%}
{%- if param.type|lower == "string" -%}
EncodeNullableForString(clientMessage, {{ param_name(param.name) }})
{%- else -%}
EncodeNullable(clientMessage, {{ param_name(param.name) }}, Encode{{ lang_name(param.type) }}{% if loop_last %}, True{% endif %})
{%- endif -%}
{%- else -%}
Encode{{ lang_name(param.type) }}(clientMessage, {{ param_name(param.name) }}{% if loop_last %}, True{% endif %})
{%- endif %}
{% endif %}
{%- endmacro %}
{% macro decode_var_sized(param) -%}
{%- if is_var_sized_list(param.type) or is_var_sized_list_contains_nullable(param.type) -%}
Decode{% if param.nullable %}Nullable{% endif %}ListMultiFrameFor{{ item_type(lang_name, param.type) }}{% if is_var_sized_list_contains_nullable(param.type) %}ContainsNullable{% endif %}(frameIterator)
{%- elif is_var_sized_entry_list(param.type) -%}
Decode{% if param.nullable %}Nullable{% endif %}EntryListFor{{ key_type(lang_name, param.type) }}And{{ value_type(lang_name, param.type) }}(frameIterator)
{%- elif is_var_sized_map(param.type) -%}
Decode{% if param.nullable %}Nullable{% endif %}Map(v, Decode{{ key_type(lang_name, param.type) }}, Decode{{ value_type(lang_name, param.type) }})
{%- else -%}
{%- if param.nullable -%}
DecodeNullableFor{{ lang_name(param.type) }}(frameIterator)
{%- else -%}
Decode{{ lang_name(param.type) }}(frameIterator)
{%- endif -%}
{%- endif -%}
{%- endmacro %}
{% macro insert_import_statements(stmts) %}
import (
{% for stmt in stmts %}
{{ stmt }}
{% endfor %}
)
{% endmacro %}
{% set request_fix_sized_params = fixed_params(method.request.params) %}
{% set request_var_sized_params = var_size_params(method.request.params) %}
{% set response_fix_sized_params = fixed_params(method.response.params) %}
{% set response_var_sized_params = var_size_params(method.response.params) %}
{% set response_new_params = new_params(method.since, method.response.params) %}
{% set event_fix_sized_params = [] %}
{% set event_var_sized_params = [] %}
{% if method.events|length != 0 %}
{% for event in method.events %}
{% do event_fix_sized_params.extend(fixed_params(event.params)) %}
{% do event_var_sized_params.extend(var_size_params(event.params)) %}
{% endfor %}
{% endif %}
/*
* Copyright (c) 2008-{{ copyright_year }}, Hazelcast, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package codec

{{ insert_import_statements(
get_import_path_holders(
request_fix_sized_params,
request_var_sized_params,
response_fix_sized_params,
response_var_sized_params,
event_fix_sized_params,
event_var_sized_params
)
)}}

const(
{{ service_name|capital }}{{ method.name|capital }}CodecRequestMessageType = int32({{ '0x%06X'|format(method.request.id) }})
{{ service_name|capital }}{{ method.name|capital }}CodecResponseMessageType = int32({{ '0x%06X'|format(method.response.id) }})

{% for event in method.events%}
{{ service_name|capital }}{{ method.name|capital }}CodecEvent{{ event.name|capital }}MessageType = int32({{ '0x%06X'|format(event.id) }})

{% endfor %}
{#FIXED SIZED PARAMETER OFFSET CONSTANTS#}
{% for param in request_fix_sized_params %}
{{ service_name|capital }}{{ method.name|capital }}CodecRequest{{ param.name|capital }}Offset = {% if loop.first %}proto.PartitionIDOffset + proto.IntSizeInBytes{% else %}{{ service_name|capital }}{{ method.name|capital }}CodecRequest{{ loop.previtem.name|capital }}Offset + proto.{{ loop.previtem.type|capitalize }}SizeInBytes{% endif %}

{% if loop.last %}
{{ service_name|capital }}{{ method.name|capital }}CodecRequestInitialFrameSize = {{ service_name|capital }}{{ method.name|capital }}CodecRequest{{ param.name|capital }}Offset + proto.{{ param.type|capitalize }}SizeInBytes

{% endif %}
{% else %}
{{ service_name|capital }}{{ method.name|capital }}CodecRequestInitialFrameSize = proto.PartitionIDOffset + proto.IntSizeInBytes

{% endfor %}
{% for param in response_fix_sized_params %}
{{ service_name|capital }}{{ method.name|capital }}Response{{ param.name|capital }}Offset = {% if loop.first %}proto.ResponseBackupAcksOffset + proto.ByteSizeInBytes{% else %}{{ service_name|capital }}{{ method.name|capital }}Response{{ loop.previtem.name|capital }}Offset + proto.{{ loop.previtem.type|capitalize }}SizeInBytes{% endif %}

{% endfor %}
{% for event in method.events %}
{% for param in fixed_params(event.params) %}
{{ service_name|capital }}{{ method.name|capital }}Event{{ event.name|capital }}{{param.name|capital}}Offset = {% if loop.first %}proto.PartitionIDOffset + proto.IntSizeInBytes{% else %}{{ service_name|capital }}{{ method.name|capital }}Event{{ event.name|capital }}{{ loop.previtem.name|capital }}Offset + proto.{{loop.previtem.type|capitalize}}SizeInBytes{% endif %}

{% endfor %}
{% endfor %}
)
{#RESPONSE PARAMETERS#}
{% set noResponseValue = method.response.params|length == 0 %}
{% set singleResponseValue = method.response.params|length == 1 and response_new_params|length == 0 %}

{% for line in method.doc.splitlines() %}
// {{ line }}
{% endfor %}

func Encode{{ service_name|capital }}{{ method.name|capital }}Request({% for param in method.request.params %}{{ escape_keyword(param.name) }} {{ lang_types_encode(param.type) }}{% if not loop.last %}, {% endif %}{% endfor %}) *proto.ClientMessage {
clientMessage := proto.NewClientMessageForEncode()
clientMessage.SetRetryable({{ method.request.retryable|lower }})

initialFrame := proto.NewFrameWith(make([]byte, {{ service_name|capital }}{{ method.name|capital }}CodecRequestInitialFrameSize), proto.UnfragmentedMessage)
{% for param in request_fix_sized_params %}
Encode{{ param.type|capital }}(initialFrame.Content, {{ service_name|capital }}{{ method.name|capital }}CodecRequest{{ param.name|capital }}Offset, {{ escape_keyword(param.name) }})
{% endfor %}
clientMessage.AddFrame(initialFrame)
clientMessage.SetMessageType({{ service_name|capital }}{{ method.name|capital }}CodecRequestMessageType)
clientMessage.SetPartitionId(-1)

{% for param in request_var_sized_params %}
{{ encode_var_sized(param) }}
{% endfor %}

return clientMessage
}

{#RESPONSE DECODE#}
{% if noResponseValue %}
{% elif singleResponseValue %}
{% set param = method.response.params|last %}
func Decode{{ service_name|capital }}{{ method.name|capital }}Response(clientMessage *proto.ClientMessage) {{ lang_types_decode(param.type) }} {
frameIterator := clientMessage.FrameIterator()
{% if response_fix_sized_params|length != 0 %}
initialFrame := frameIterator.Next()
{% else %}
// empty initial frame
frameIterator.Next()
{% endif %}

{% for param in response_fix_sized_params %}
return Decode{{ param.type|capital }}(initialFrame.Content, {{ service_name|capital }}{{ method.name|capital }}Response{{param.name|capital}}Offset)
{% endfor %}
{% for param in response_var_sized_params %}
return {{ decode_var_sized(param) }}
{% endfor %}
}
{% else %}
func Decode{{ service_name|capital }}{{ method.name|capital }}Response(clientMessage *proto.ClientMessage) ({% for param in method.response.params %}{{ escape_keyword(param.name)}} {{ lang_types_encode(param.type) }}{{ ", " if not loop.last }}{% endfor %}{% for new_param in response_new_params %} is{{ new_param.name|capital }}Exists bool{% endfor %}) {
{% if response_fix_sized_params|length != 0 %}
frameIterator := clientMessage.FrameIterator()
initialFrame := frameIterator.Next()
{% else %}
frameIterator := clientMessage.FrameIterator()
frameIterator.Next()
{% endif %}

{% for param in response_fix_sized_params %}
{% if param in response_new_params %}
if (initialFrame.content.length >= RESPONSE_{{ to_upper_snake_case(param.name) }}_OFFSET + BitsUtil.{{ param.type.upper() }}_SIZE_IN_BYTES) {
response.{{ escape_keyword(param.name) }} = Decode{{ param.type|capital }}(initialFrame.Content, RESPONSE_{{to_upper_snake_case(param.name)}}_OFFSET);
response.is{{ param.name|capital }}Exists = true;
} else {
response.is{{ param.name|capital }}Exists = false;
}
{% else %}
{{ escape_keyword(param.name) }} = Decode{{ param.type|capital }}(initialFrame.Content, {{ service_name|capital }}{{ method.name|capital }}Response{{ param.name|capital }}Offset)
{% endif %}
{% endfor %}
{% for param in response_var_sized_params %}
{% if param in response_new_params %}
if (clientMessage.hasNextFrame()) {
response.{{ escape_keyword(param.name) }} = {{ decode_var_sized(param) }};
response.is{{ param.name|capital }}Exists = true;
} else {
response.is{{ param.name|capital }}Exists = false;
}
{% else %}
{{ escape_keyword(param.name) }} = {{ decode_var_sized(param) }}
{% endif %}
{% endfor %}

return {% for param in method.response.params %}{{ escape_keyword(param.name)}}{{ ", " if not loop.last }}{% endfor %} {% for new_param in response_new_params %} is{{ new_param.name|capital }}Exists bool{% endfor %}
}
{% endif %}
{# EVENTS#}
{% if method.events|length != 0 %}

func Handle{{ service_name|capital }}{{ method.name|capital }}(clientMessage *proto.ClientMessage, {% for event in method.events%}handle{{ event.name|capital }}Event func({% for param in event.params %}{{param.name}} {{ lang_types_encode(param.type) }}{% if not loop.last %}, {% endif %}{% endfor %}){% if not loop.last %}, {% endif %}{% endfor %}){
messageType := clientMessage.Type()
frameIterator := clientMessage.FrameIterator()
{% for event in method.events%}
if messageType == {{ service_name|capital }}{{ method.name|capital }}CodecEvent{{ event.name|capital }}MessageType {
{% set new_event_params = new_params(event.since, event.params) %}
{% if fixed_params(event.params)|length != 0 %}
initialFrame := frameIterator.Next()
{% else %}
//empty initial frame
frameIterator.Next()
{% endif %}
{% for param in fixed_params(event.params) %}
{% if param in new_event_params %}
let is{{ param.name|capital }}Exists = false
let {{ escape_keyword(param.name) }} = {% if param.type == 'boolean' %}false{% elif param.type == 'UUID' %}null{% else %}0{% endif %}
if (initialFrame.content.length >= EVENT_{{ to_upper_snake_case(event.name)}}_{{ to_upper_snake_case(param.name) }}_OFFSET + BitsUtil.{{ param.type.upper() }}_SIZE_IN_BYTES) {
{{ escape_keyword(param.name) }} = Decode{{ param.type|capital }}(initialFrame.content, EVENT_{{ to_upper_snake_case(event.name)}}_{{ to_upper_snake_case(param.name) }}_OFFSET)
is{{ param.name|capital }}Exists = true;
}
{% else %}
{{ escape_keyword(param.name) }} := Decode{{ param.type|capital }}(initialFrame.Content, {{ service_name|capital }}{{ method.name|capital }}Event{{ event.name|capital }}{{param.name|capital}}Offset)
{% endif %}
{% endfor %}
{% for param in var_size_params(event.params) %}
{% if param in new_event_params %}
let is{{ param.name|capital }}Exists = false
let {{ escape_keyword(param.name) }} = null
if (iterator.hasNextFrame()) {
{{ escape_keyword(param.name) }} = {{ decode_var_sized(param) }}
is{{ param.name|capital }}Exists = true;
}
{% else %}
{{ escape_keyword(param.name) }} := {{ decode_var_sized(param) }}
{% endif %}
{% endfor %}
handle{{ event.name|capital }}Event({% for param in event.params %}{% if param in new_event_params %}is{{ param.name|capital }}Exists, {% endif %}{{param.name}}{% if not loop.last %}, {% endif %}{% endfor %})
return
}
{% endfor %}
}
{% endif %}
13 changes: 13 additions & 0 deletions go/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"include_methods": ["Map.*"],
"include_types": ["Address"],
"mapping": {
"Address": "pubcluster.Address",
"longArray": "[]int64",
"List_String": "[]string",
"List_UUID": "[]types.UUID",
"List_Long": "[]int64",
"EntryList_String_EntryList_Integer_Long": "map[string]map[int32]int64",
"EntryList_Integer_UUID": "map[int32]types.UUID"
}
}
25 changes: 25 additions & 0 deletions go/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

DEFAULT_IMPORT_PATH = "github.com/hazelcast/hazelcast-go-client"


class Config:

def __init__(self, base_import_path="", include_methods=None, include_types=None, mapping=None, override_imports=None, types=None):
self.base_import_path = base_import_path or DEFAULT_IMPORT_PATH
self.include_methods = include_methods or []
self.include_types = include_types or []
self.mapping = mapping or {}
self.override_imports = override_imports or {}
self.types = types or {}

@classmethod
def from_json(cls, d: dict):
keys = [
"base_import_path",
"include_methods",
"include_types",
"mapping",
"override_imports",
"types"
]
return cls(**{k: d.get(k) for k in keys})
Loading
Loading