diff --git a/changelogs/unreleased/gh-8574-export-iproto-auth-type.md b/changelogs/unreleased/gh-8574-export-iproto-auth-type.md new file mode 100644 index 0000000000000000000000000000000000000000..8d26cd58c136429d8a2dd8bcac3a859bb6b643b9 --- /dev/null +++ b/changelogs/unreleased/gh-8574-export-iproto-auth-type.md @@ -0,0 +1,3 @@ +## bugfix/lua + +* Exported the missing `AUTH_TYPE` key to `box.iproto.key` (gh-8574). diff --git a/changelogs/unreleased/gh-8577-strip-prefix-pagination-iproto-keys.md b/changelogs/unreleased/gh-8577-strip-prefix-pagination-iproto-keys.md new file mode 100644 index 0000000000000000000000000000000000000000..a366c3db8ebd0b0572a33f71d83856a6c72829ee --- /dev/null +++ b/changelogs/unreleased/gh-8577-strip-prefix-pagination-iproto-keys.md @@ -0,0 +1,4 @@ +## bugfix/lua + +* Stripped the unwanted `IPROTO_` prefix from the `POSITION`, `AFTER_POSITION`, + and `AFTER_TUPLE` keys exported to `box.iproto.key` (gh-8577). diff --git a/src/box/iproto_constants.c b/src/box/iproto_constants.c index 86391b06a75e0c855a9ae87f9849ed3d774ad54b..1fc05f3a66d715ccbbf8aebc509f24e3dff96eb0 100644 --- a/src/box/iproto_constants.c +++ b/src/box/iproto_constants.c @@ -317,3 +317,42 @@ const char *vy_row_index_key_strs[VY_ROW_INDEX_KEY_MAX] = { NULL, "row index", }; + +const struct iproto_constant iproto_flag_constants[] = { + IPROTO_FLAGS(IPROTO_CONSTANT_MEMBER) +}; + +const size_t iproto_flag_constants_size = lengthof(iproto_flag_constants); + +const struct iproto_constant iproto_key_constants[] = { + IPROTO_KEYS(IPROTO_CONSTANT_MEMBER) +}; + +const size_t iproto_key_constants_size = lengthof(iproto_key_constants); + +const struct iproto_constant iproto_metadata_key_constants[] = { + IPROTO_METADATA_KEYS(IPROTO_CONSTANT_MEMBER) +}; + +const size_t iproto_metadata_key_constants_size = + lengthof(iproto_metadata_key_constants); + +const struct iproto_constant iproto_ballot_key_constants[] = { + IPROTO_BALLOT_KEYS(IPROTO_CONSTANT_MEMBER) +}; + +const size_t iproto_ballot_key_constants_size = + lengthof(iproto_ballot_key_constants); + +const struct iproto_constant iproto_type_constants[] = { + IPROTO_TYPES(IPROTO_CONSTANT_MEMBER) +}; + +const size_t iproto_type_constants_size = lengthof(iproto_type_constants); + +const struct iproto_constant iproto_raft_keys_constants[] = { + IPROTO_RAFT_KEYS(IPROTO_CONSTANT_MEMBER) +}; + +const size_t iproto_raft_keys_constants_size = + lengthof(iproto_raft_keys_constants); diff --git a/src/box/iproto_constants.h b/src/box/iproto_constants.h index aca2cf0492275f717ae88765f6056e0216d74501..38c2e20976f6e9162a7da40b6da7c87f4dd0f951 100644 --- a/src/box/iproto_constants.h +++ b/src/box/iproto_constants.h @@ -40,6 +40,16 @@ extern "C" { #endif +/** Named IPROTO constant. */ +struct iproto_constant { + /** NULL-terminated name of constant. */ + const char *name; + /** Value of constant. */ + int value; +}; + +#define IPROTO_CONSTANT_MEMBER(s, v) {.name = #s, .value = v}, + enum { /** Maximal iproto package body length (2GiB) */ IPROTO_BODY_LEN_MAX = 2147483648UL, @@ -49,174 +59,195 @@ enum { XLOG_FIXHEADER_SIZE = 19 }; -/** - * IPROTO_FLAGS bitfield constants. - * `box.iproto.flag` needs to be updated correspondingly. - */ -enum { - /** Set for the last xrow in a transaction. */ - IPROTO_FLAG_COMMIT = 0x01, - /** Set for the last row of a tx residing in limbo. */ - IPROTO_FLAG_WAIT_SYNC = 0x02, - /** Set for the last row of a synchronous tx. */ - IPROTO_FLAG_WAIT_ACK = 0x04, -}; - -/** - * `box.iproto.key` needs to be updated correspondingly. - */ -enum iproto_key { - IPROTO_REQUEST_TYPE = 0x00, - IPROTO_SYNC = 0x01, - - /* Replication keys (header) */ - IPROTO_REPLICA_ID = 0x02, - IPROTO_LSN = 0x03, - IPROTO_TIMESTAMP = 0x04, - IPROTO_SCHEMA_VERSION = 0x05, - IPROTO_SERVER_VERSION = 0x06, - IPROTO_GROUP_ID = 0x07, - IPROTO_TSN = 0x08, - IPROTO_FLAGS = 0x09, - IPROTO_STREAM_ID = 0x0a, - /* Leave a gap for other keys in the header. */ - IPROTO_SPACE_ID = 0x10, - IPROTO_INDEX_ID = 0x11, - IPROTO_LIMIT = 0x12, - IPROTO_OFFSET = 0x13, - IPROTO_ITERATOR = 0x14, - IPROTO_INDEX_BASE = 0x15, - /* Leave a gap between integer values and other keys */ +/** IPROTO_FLAGS bitfield constants. */ +#define IPROTO_FLAGS(_) \ + /** Set for the last xrow in a transaction. */ \ + _(IPROTO_FLAG_COMMIT, 0x01) \ + /** Set for the last row of a tx residing in limbo. */ \ + _(IPROTO_FLAG_WAIT_SYNC, 0x02) \ + /** Set for the last row of a synchronous tx. */ \ + _(IPROTO_FLAG_WAIT_ACK, 0x04) \ + +ENUM(iproto_flag, IPROTO_FLAGS); + +/** Constants generated from IPROTO_FLAGS. */ +extern const struct iproto_constant iproto_flag_constants[]; + +/** Size of iproto_flag_constants. */ +extern const size_t iproto_flag_constants_size; + +#define IPROTO_KEYS(_) \ + _(IPROTO_REQUEST_TYPE, 0x00) \ + _(IPROTO_SYNC, 0x01) \ + \ + /* Replication keys (header) */ \ + _(IPROTO_REPLICA_ID, 0x02) \ + _(IPROTO_LSN, 0x03) \ + _(IPROTO_TIMESTAMP, 0x04) \ + _(IPROTO_SCHEMA_VERSION, 0x05) \ + _(IPROTO_SERVER_VERSION, 0x06) \ + _(IPROTO_GROUP_ID, 0x07) \ + _(IPROTO_TSN, 0x08) \ + _(IPROTO_FLAGS, 0x09) \ + _(IPROTO_STREAM_ID, 0x0a) \ + /* Leave a gap for other keys in the header. */ \ + _(IPROTO_SPACE_ID, 0x10) \ + _(IPROTO_INDEX_ID, 0x11) \ + _(IPROTO_LIMIT, 0x12) \ + _(IPROTO_OFFSET, 0x13) \ + _(IPROTO_ITERATOR, 0x14) \ + _(IPROTO_INDEX_BASE, 0x15) \ + /* Leave a gap between integer values and other keys */ \ /** * Flag indicating the need to send position of * last selected tuple in response. - */ - IPROTO_FETCH_POSITION = 0x1f, - IPROTO_KEY = 0x20, - IPROTO_TUPLE = 0x21, - IPROTO_FUNCTION_NAME = 0x22, - IPROTO_USER_NAME = 0x23, - + */ \ + _(IPROTO_FETCH_POSITION, 0x1f) \ + _(IPROTO_KEY, 0x20) \ + _(IPROTO_TUPLE, 0x21) \ + _(IPROTO_FUNCTION_NAME, 0x22) \ + _(IPROTO_USER_NAME, 0x23) \ + \ /* * Replication keys (body). * Unfortunately, there is no gap between request and * replication keys (between USER_NAME and INSTANCE_UUID). * So imagine, that OPS, EXPR and FIELD_NAME keys follows * the USER_NAME key. - */ - IPROTO_INSTANCE_UUID = 0x24, - IPROTO_REPLICASET_UUID = 0x25, - IPROTO_VCLOCK = 0x26, - - /* Also request keys. See the comment above. */ - IPROTO_EXPR = 0x27, /* EVAL */ - IPROTO_OPS = 0x28, /* UPSERT but not UPDATE ops, because of legacy */ - IPROTO_BALLOT = 0x29, - IPROTO_TUPLE_META = 0x2a, - IPROTO_OPTIONS = 0x2b, - /** Old tuple (i.e. before DML request is applied). */ - IPROTO_OLD_TUPLE = 0x2c, - /** New tuple (i.e. result of DML request). */ - IPROTO_NEW_TUPLE = 0x2d, - /** Position of last selected tuple to start iteration after it. */ - IPROTO_AFTER_POSITION = 0x2e, - /** Last selected tuple to start iteration after it. */ - IPROTO_AFTER_TUPLE = 0x2f, - - /** Response keys. */ - IPROTO_DATA = 0x30, - IPROTO_ERROR_24 = 0x31, + */ \ + _(IPROTO_INSTANCE_UUID, 0x24) \ + _(IPROTO_REPLICASET_UUID, 0x25) \ + _(IPROTO_VCLOCK, 0x26) \ + \ + /* Also request keys. See the comment above. */ \ + _(IPROTO_EXPR, 0x27) /* EVAL */ \ + /* UPSERT but not UPDATE ops, because of legacy */ \ + _(IPROTO_OPS, 0x28) \ + _(IPROTO_BALLOT, 0x29) \ + _(IPROTO_TUPLE_META, 0x2a) \ + _(IPROTO_OPTIONS, 0x2b) \ + /** Old tuple (i.e. before DML request is applied). */ \ + _(IPROTO_OLD_TUPLE, 0x2c) \ + /** New tuple (i.e. result of DML request). */ \ + _(IPROTO_NEW_TUPLE, 0x2d) \ + /** + * Position of last selected tuple to start iteration after it. + */ \ + _(IPROTO_AFTER_POSITION, 0x2e) \ + /** Last selected tuple to start iteration after it. */ \ + _(IPROTO_AFTER_TUPLE, 0x2f) \ + \ + /** Response keys. */ \ + _(IPROTO_DATA, 0x30) \ + _(IPROTO_ERROR_24, 0x31) \ /** * IPROTO_METADATA: [ * { IPROTO_FIELD_NAME: name }, * { ... }, * ... * ] - */ - IPROTO_METADATA = 0x32, - IPROTO_BIND_METADATA = 0x33, - IPROTO_BIND_COUNT = 0x34, - /** Position of last selected tuple in response. */ - IPROTO_POSITION = 0x35, - - /* Leave a gap between response keys and SQL keys. */ - IPROTO_SQL_TEXT = 0x40, - IPROTO_SQL_BIND = 0x41, + */ \ + _(IPROTO_METADATA, 0x32) \ + _(IPROTO_BIND_METADATA, 0x33) \ + _(IPROTO_BIND_COUNT, 0x34) \ + /** Position of last selected tuple in response. */ \ + _(IPROTO_POSITION, 0x35) \ + \ + /* Leave a gap between response keys and SQL keys. */ \ + _(IPROTO_SQL_TEXT, 0x40) \ + _(IPROTO_SQL_BIND, 0x41) \ /** * IPROTO_SQL_INFO: { - * SQL_INFO_ROW_COUNT: number + * SQL_INFO_ROW_COUNT: number * } - */ - IPROTO_SQL_INFO = 0x42, - IPROTO_STMT_ID = 0x43, - /* Leave a gap between SQL keys and additional request keys */ - IPROTO_REPLICA_ANON = 0x50, - IPROTO_ID_FILTER = 0x51, - IPROTO_ERROR = 0x52, + */ \ + _(IPROTO_SQL_INFO, 0x42) \ + _(IPROTO_STMT_ID, 0x43) \ + /* Leave a gap between SQL keys and additional request keys */ \ + _(IPROTO_REPLICA_ANON, 0x50) \ + _(IPROTO_ID_FILTER, 0x51) \ + _(IPROTO_ERROR, 0x52) \ /** * Term. Has the same meaning as IPROTO_RAFT_TERM, but is an iproto * key, rather than a raft key. Used for PROMOTE request, which needs * both iproto (e.g. REPLICA_ID) and raft (RAFT_TERM) keys. - */ - IPROTO_TERM = 0x53, - /** Protocol version. */ - IPROTO_VERSION = 0x54, - /** Protocol features. */ - IPROTO_FEATURES = 0x55, - /** Operation timeout. Specific to request type. */ - IPROTO_TIMEOUT = 0x56, - /** Key name and data sent to a remote watcher. */ - IPROTO_EVENT_KEY = 0x57, - IPROTO_EVENT_DATA = 0x58, - /** Isolation level, is used only by IPROTO_BEGIN request. */ - IPROTO_TXN_ISOLATION = 0x59, - /** A vclock synchronisation request identifier. */ - IPROTO_VCLOCK_SYNC = 0x5a, + */ \ + _(IPROTO_TERM, 0x53) \ + /** Protocol version. */ \ + _(IPROTO_VERSION, 0x54) \ + /** Protocol features. */ \ + _(IPROTO_FEATURES, 0x55) \ + /** Operation timeout. Specific to request type. */ \ + _(IPROTO_TIMEOUT, 0x56) \ + /** Key name and data sent to a remote watcher. */ \ + _(IPROTO_EVENT_KEY, 0x57) \ + _(IPROTO_EVENT_DATA, 0x58) \ + /** Isolation level, is used only by IPROTO_BEGIN request. */ \ + _(IPROTO_TXN_ISOLATION, 0x59) \ + /** A vclock synchronisation request identifier. */ \ + _(IPROTO_VCLOCK_SYNC, 0x5a) \ /** * Name of the authentication method that is currently used on * the server (value of box.cfg.auth_type). It's sent in reply * to IPROTO_ID request. A client can use it as the default * authentication method. - */ - IPROTO_AUTH_TYPE = 0x5b, - /* - * Be careful to not extend iproto_key values over 0x7f. - * iproto_keys are encoded in msgpack as positive fixnum, which ends at - * 0x7f, and we rely on this in some places by allocating a uint8_t to - * hold a msgpack-encoded key value. - */ - iproto_key_MAX -}; + */ \ + _(IPROTO_AUTH_TYPE, 0x5b) \ + +ENUM(iproto_key, IPROTO_KEYS); +/** + * Be careful not to extend iproto_key values over 0x7f. + * iproto_keys are encoded in msgpack as positive fixnum, which ends at + * 0x7f, and we rely on this in some places by allocating a uint8_t to + * hold a msgpack-encoded key value. + */ +static_assert(iproto_key_MAX <= 0x80, "iproto_key_MAX must be <= 0x80"); + +/** Constants generated from IPROTO_KEYS. */ +extern const struct iproto_constant iproto_key_constants[]; + +/** Size of iproto_key_constants. */ +extern const size_t iproto_key_constants_size; /** * Keys, stored in IPROTO_METADATA. They can not be received * in a request. Only sent as response, so no necessity in _strs * or _key_type arrays. - * `box.iproto.metadata_key` needs to be updated correspondingly. */ -enum iproto_metadata_key { - IPROTO_FIELD_NAME = 0, - IPROTO_FIELD_TYPE = 1, - IPROTO_FIELD_COLL = 2, - IPROTO_FIELD_IS_NULLABLE = 3, - IPROTO_FIELD_IS_AUTOINCREMENT = 4, - IPROTO_FIELD_SPAN = 5, -}; +#define IPROTO_METADATA_KEYS(_) \ + _(IPROTO_FIELD_NAME, 0) \ + _(IPROTO_FIELD_TYPE, 1) \ + _(IPROTO_FIELD_COLL, 2) \ + _(IPROTO_FIELD_IS_NULLABLE, 3) \ + _(IPROTO_FIELD_IS_AUTOINCREMENT, 4) \ + _(IPROTO_FIELD_SPAN, 5) \ -/** - * `box.iproto.ballot_key` needs to be updated correspondingly. - */ -enum iproto_ballot_key { - IPROTO_BALLOT_IS_RO_CFG = 0x01, - IPROTO_BALLOT_VCLOCK = 0x02, - IPROTO_BALLOT_GC_VCLOCK = 0x03, - IPROTO_BALLOT_IS_RO = 0x04, - IPROTO_BALLOT_IS_ANON = 0x05, - IPROTO_BALLOT_IS_BOOTED = 0x06, - IPROTO_BALLOT_CAN_LEAD = 0x07, - IPROTO_BALLOT_BOOTSTRAP_LEADER_UUID = 0x08, - IPROTO_BALLOT_REGISTERED_REPLICA_UUIDS = 0x09, -}; +ENUM(iproto_metadata_key, IPROTO_METADATA_KEYS); + +/** Constants generated from IPROTO_METADATA_KEYS. */ +extern const struct iproto_constant iproto_metadata_key_constants[]; + +/** Size of iproto_metadata_key_constants. */ +extern const size_t iproto_metadata_key_constants_size; + +#define IPROTO_BALLOT_KEYS(_) \ + _(IPROTO_BALLOT_IS_RO_CFG, 0x01) \ + _(IPROTO_BALLOT_VCLOCK, 0x02) \ + _(IPROTO_BALLOT_GC_VCLOCK, 0x03) \ + _(IPROTO_BALLOT_IS_RO, 0x04) \ + _(IPROTO_BALLOT_IS_ANON, 0x05) \ + _(IPROTO_BALLOT_IS_BOOTED, 0x06) \ + _(IPROTO_BALLOT_CAN_LEAD, 0x07) \ + _(IPROTO_BALLOT_BOOTSTRAP_LEADER_UUID, 0x08) \ + _(IPROTO_BALLOT_REGISTERED_REPLICA_UUIDS, 0x09) \ + +ENUM(iproto_ballot_key, IPROTO_BALLOT_KEYS); + +/** Constants generated from IPROTO_BALLOT_KEYS. */ +extern const struct iproto_constant iproto_ballot_key_constants[]; + +/** Size of iproto_ballot_key_constants. */ +extern const size_t iproto_ballot_key_constants_size; static inline uint64_t iproto_key_bit(unsigned char key) @@ -226,78 +257,77 @@ iproto_key_bit(unsigned char key) extern const unsigned char iproto_key_type[iproto_key_MAX]; -/** - * IPROTO command codes. - * `box.iproto.type` needs to be updated correspondingly. - */ -enum iproto_type { - /** Acknowledgement that request or command is successful */ - IPROTO_OK = 0, - - /** SELECT request */ - IPROTO_SELECT = 1, - /** INSERT request */ - IPROTO_INSERT = 2, - /** REPLACE request */ - IPROTO_REPLACE = 3, - /** UPDATE request */ - IPROTO_UPDATE = 4, - /** DELETE request */ - IPROTO_DELETE = 5, - /** CALL request - wraps result into [tuple, tuple, ...] format */ - IPROTO_CALL_16 = 6, - /** AUTH request */ - IPROTO_AUTH = 7, - /** EVAL request */ - IPROTO_EVAL = 8, - /** UPSERT request */ - IPROTO_UPSERT = 9, - /** CALL request - returns arbitrary MessagePack */ - IPROTO_CALL = 10, - /** Execute an SQL statement. */ - IPROTO_EXECUTE = 11, - /** No operation. Treated as DML, used to bump LSN. */ - IPROTO_NOP = 12, - /** Prepare SQL statement. */ - IPROTO_PREPARE = 13, - /* Begin transaction */ - IPROTO_BEGIN = 14, - /* Commit transaction */ - IPROTO_COMMIT = 15, - /* Rollback transaction */ - IPROTO_ROLLBACK = 16, - /** The maximum typecode used for box.stat() */ - IPROTO_TYPE_STAT_MAX, - - IPROTO_RAFT = 30, - /** PROMOTE request. */ - IPROTO_RAFT_PROMOTE = 31, - /** DEMOTE request. */ - IPROTO_RAFT_DEMOTE = 32, - - /** A confirmation message for synchronous transactions. */ - IPROTO_RAFT_CONFIRM = 40, - /** A rollback message for synchronous transactions. */ - IPROTO_RAFT_ROLLBACK = 41, - - /** PING request */ - IPROTO_PING = 64, - /** Replication JOIN command */ - IPROTO_JOIN = 65, - /** Replication SUBSCRIBE command */ - IPROTO_SUBSCRIBE = 66, - /** DEPRECATED: use IPROTO_VOTE instead */ - IPROTO_VOTE_DEPRECATED = 67, - /** Vote request command for master election */ - IPROTO_VOTE = 68, - /** Anonymous replication FETCH SNAPSHOT. */ - IPROTO_FETCH_SNAPSHOT = 69, - /** REGISTER request to leave anonymous replication. */ - IPROTO_REGISTER = 70, - IPROTO_JOIN_META = 71, - IPROTO_JOIN_SNAPSHOT = 72, - /** Protocol features request. */ - IPROTO_ID = 73, +/** IPROTO command codes. */ +#define IPROTO_TYPES(_) \ + /** Acknowledgement that request or command is successful */ \ + _(IPROTO_OK, 0) \ + \ + /** SELECT request */ \ + _(IPROTO_SELECT, 1) \ + /** INSERT request */ \ + _(IPROTO_INSERT, 2) \ + /** REPLACE request */ \ + _(IPROTO_REPLACE, 3) \ + /** UPDATE request */ \ + _(IPROTO_UPDATE, 4) \ + /** DELETE request */ \ + _(IPROTO_DELETE, 5) \ + /** + * CALL request - wraps result into [tuple, tuple, ...] format + */ \ + _(IPROTO_CALL_16, 6) \ + /** AUTH request */ \ + _(IPROTO_AUTH, 7) \ + /** EVAL request */ \ + _(IPROTO_EVAL, 8) \ + /** UPSERT request */ \ + _(IPROTO_UPSERT, 9) \ + /** CALL request - returns arbitrary MessagePack */ \ + _(IPROTO_CALL, 10) \ + /** Execute an SQL statement. */ \ + _(IPROTO_EXECUTE, 11) \ + /** No operation. Treated as DML, used to bump LSN. */ \ + _(IPROTO_NOP, 12) \ + /** Prepare SQL statement. */ \ + _(IPROTO_PREPARE, 13) \ + /* Begin transaction */ \ + _(IPROTO_BEGIN, 14) \ + /* Commit transaction */ \ + _(IPROTO_COMMIT, 15) \ + /* Rollback transaction */ \ + _(IPROTO_ROLLBACK, 16) \ + /** The maximum typecode used for box.stat() */ \ + _(IPROTO_RESERVED_TYPE_STAT_MAX, 17) \ + \ + _(IPROTO_RAFT, 30) \ + /** PROMOTE request. */ \ + _(IPROTO_RAFT_PROMOTE, 31) \ + /** DEMOTE request. */ \ + _(IPROTO_RAFT_DEMOTE, 32) \ + \ + /** A confirmation message for synchronous transactions. */ \ + _(IPROTO_RAFT_CONFIRM, 40) \ + /** A rollback message for synchronous transactions. */ \ + _(IPROTO_RAFT_ROLLBACK, 41) \ + \ + /** PING request */ \ + _(IPROTO_PING, 64) \ + /** Replication JOIN command */ \ + _(IPROTO_JOIN, 65) \ + /** Replication SUBSCRIBE command */ \ + _(IPROTO_SUBSCRIBE, 66) \ + /** DEPRECATED: use IPROTO_VOTE instead */ \ + _(IPROTO_VOTE_DEPRECATED, 67) \ + /** Vote request command for master election */ \ + _(IPROTO_VOTE, 68) \ + /** Anonymous replication FETCH SNAPSHOT. */ \ + _(IPROTO_FETCH_SNAPSHOT, 69) \ + /** REGISTER request to leave anonymous replication. */ \ + _(IPROTO_REGISTER, 70) \ + _(IPROTO_JOIN_META, 71) \ + _(IPROTO_JOIN_SNAPSHOT, 72) \ + /** Protocol features request. */ \ + _(IPROTO_ID, 73) \ /** * The following three request types are used by the remote watcher * protocol (box.watch over network), which operates as follows: @@ -317,46 +347,68 @@ enum iproto_type { * doesn't send a packet in reply to any of them. Still, the server * sends the same sync number in an IPROTO_EVENT packet as the one sent * by the client in the last corresponding IPROTO_WATCH request. - */ - IPROTO_WATCH = 74, - IPROTO_UNWATCH = 75, - IPROTO_EVENT = 76, - - /** Vinyl run info stored in .index file */ - VY_INDEX_RUN_INFO = 100, - /** Vinyl page info stored in .index file */ - VY_INDEX_PAGE_INFO = 101, - /** Vinyl row index stored in .run file */ - VY_RUN_ROW_INDEX = 102, - - /** Non-final response type. */ - IPROTO_CHUNK = 128, - + */ \ + _(IPROTO_WATCH, 74) \ + _(IPROTO_UNWATCH, 75) \ + _(IPROTO_EVENT, 76) \ + /** + * The following three requests are reserved for vinyl types. + */ \ + _(IPROTO_RESERVED_VY_INDEX_RUN_INFO, 100) \ + _(IPROTO_RESERVED_VY_INDEX_PAGE_INFO, 101) \ + _(IPROTO_RESERVED_VY_RUN_ROW_INDEX, 102) \ + \ + /** Non-final response type. */ \ + _(IPROTO_CHUNK, 128) \ + \ /** * Error codes = (IPROTO_TYPE_ERROR | ER_XXX from errcode.h) - */ - IPROTO_TYPE_ERROR = 1 << 15, - + */ \ + _(IPROTO_TYPE_ERROR, 1 << 15) \ + \ /** * Used for overriding the unknown request handler. - */ - IPROTO_UNKNOWN = -1, + */ \ + _(IPROTO_UNKNOWN, -1) \ + +ENUM(iproto_type, IPROTO_TYPES); + +/** Constants generated from IPROTO_TYPES. */ +extern const struct iproto_constant iproto_type_constants[]; + +/** Size of iproto_type_constants. */ +extern const size_t iproto_type_constants_size; + +/** Convenient synonims for reserved members of iproto_type. */ +enum { + /** The maximum typecode used for box.stat() */ + IPROTO_TYPE_STAT_MAX = IPROTO_RESERVED_TYPE_STAT_MAX, + /** Vinyl run info stored in .index file */ + VY_INDEX_RUN_INFO = IPROTO_RESERVED_VY_INDEX_RUN_INFO, + /** Vinyl page info stored in .index file */ + VY_INDEX_PAGE_INFO = IPROTO_RESERVED_VY_INDEX_PAGE_INFO, + /** Vinyl row index stored in .run file */ + VY_RUN_ROW_INDEX = IPROTO_RESERVED_VY_RUN_ROW_INDEX, }; /** IPROTO type name by code */ extern const char *iproto_type_strs[]; -/** - * `box.iproto.raft_key` needs to be updated correspondingly. - */ -enum iproto_raft_keys { - IPROTO_RAFT_TERM = 0, - IPROTO_RAFT_VOTE = 1, - IPROTO_RAFT_STATE = 2, - IPROTO_RAFT_VCLOCK = 3, - IPROTO_RAFT_LEADER_ID = 4, - IPROTO_RAFT_IS_LEADER_SEEN = 5, -}; +#define IPROTO_RAFT_KEYS(_) \ + _(IPROTO_RAFT_TERM, 0) \ + _(IPROTO_RAFT_VOTE, 1) \ + _(IPROTO_RAFT_STATE, 2) \ + _(IPROTO_RAFT_VCLOCK, 3) \ + _(IPROTO_RAFT_LEADER_ID, 4) \ + _(IPROTO_RAFT_IS_LEADER_SEEN, 5) \ + +ENUM(iproto_raft_keys, IPROTO_RAFT_KEYS); + +/** Constants generated from IPROTO_RAFT_KEYS. */ +extern const struct iproto_constant iproto_raft_keys_constants[]; + +/** Size of iproto_raft_keys_constants. */ +extern const size_t iproto_raft_keys_constants_size; /** * Returns IPROTO type name by @a type code. diff --git a/src/box/iproto_features.c b/src/box/iproto_features.c index 9499f60654d7503b43dfb3ae78ad7708aa4a0d3e..b5724381fbe3d6766686f8a345120194cf31fe7e 100644 --- a/src/box/iproto_features.c +++ b/src/box/iproto_features.c @@ -54,6 +54,13 @@ mp_decode_iproto_features(const char **data, struct iproto_features *features) return 0; } +const struct iproto_constant iproto_feature_id_constants[] = { + IPROTO_FEATURES(IPROTO_CONSTANT_MEMBER) +}; + +const size_t iproto_feature_id_constants_size = + lengthof(iproto_feature_id_constants); + void iproto_features_init(void) { diff --git a/src/box/iproto_features.h b/src/box/iproto_features.h index 4cb65b3418abfe8894f4252d8f542f630b524c11..755fde7a67d5b41fd8ae7fc9ebd3301c60f13609 100644 --- a/src/box/iproto_features.h +++ b/src/box/iproto_features.h @@ -10,26 +10,23 @@ #include <string.h> #include "bit/bit.h" +#include "iproto_constants.h" #if defined(__cplusplus) extern "C" { #endif -/** - * IPROTO protocol feature ids returned by the IPROTO_ID command. - * `box.iproto.protocol_features` and `box.iproto.feature` need to be updated - * correspondingly. - */ -enum iproto_feature_id { +/** IPROTO protocol feature ids returned by the IPROTO_ID command. */ +#define IPROTO_FEATURES(_) \ /** * Streams support: IPROTO_STREAM_ID header key. - */ - IPROTO_FEATURE_STREAMS = 0, + */ \ + _(IPROTO_FEATURE_STREAMS, 0) \ /** * Transactions in the protocol: * IPROTO_BEGIN, IPROTO_COMMIT, IPROTO_ROLLBACK commands. - */ - IPROTO_FEATURE_TRANSACTIONS = 1, + */ \ + _(IPROTO_FEATURE_TRANSACTIONS, 1) \ /** * MP_ERROR MsgPack extension support. * @@ -40,21 +37,27 @@ enum iproto_feature_id { * converted to a string error message). If the feature bit is set and * encode_errors_as_ext is true, errors will be encoded as MP_ERROR * MsgPack extension. - */ - IPROTO_FEATURE_ERROR_EXTENSION = 2, + */ \ + _(IPROTO_FEATURE_ERROR_EXTENSION, 2) \ /** * Remote watchers support: * IPROTO_WATCH, IPROTO_UNWATCH, IPROTO_EVENT commands. - */ - IPROTO_FEATURE_WATCHERS = 3, + */ \ + _(IPROTO_FEATURE_WATCHERS, 3) \ /** * Pagination support: * IPROTO_AFTER_POSITION, IPROTO_AFTER_TUPLE, IPROTO_FETCH_POSITION * request fields and IPROTO_POSITION response field. - */ - IPROTO_FEATURE_PAGINATION = 4, - iproto_feature_id_MAX, -}; + */ \ + _(IPROTO_FEATURE_PAGINATION, 4) \ + +ENUM(iproto_feature_id, IPROTO_FEATURES); + +/** Constants generated from IPROTO_FEATURES. */ +extern const struct iproto_constant iproto_feature_id_constants[]; + +/** Size of iproto_feature_id_constants. */ +extern const size_t iproto_feature_id_constants_size; /** * IPROTO protocol feature bit map. diff --git a/src/box/lua/iproto.c b/src/box/lua/iproto.c index 6db1421468bf622ebdb98b8ed0bdd355a9bc2af0..1f1f3658e44b24bb9cdbc46a1528175fe8ef403a 100644 --- a/src/box/lua/iproto.c +++ b/src/box/lua/iproto.c @@ -28,126 +28,67 @@ struct mh_strnu32_t *iproto_key_translation; -/** - * IPROTO constant from `src/box/iproto_{constants, features}.h`. - */ -struct iproto_constant { - /** - * Constant literal, name of constant. - */ - const char *const name; - /** - * Constant literal, value of constant. - */ - const lua_Integer val; -}; - /** * Pushes an array of IPROTO constants onto Lua stack. */ static void -push_iproto_constant_subnamespace(struct lua_State *L, const char *subnamespace, - const struct iproto_constant *constants, - int constants_len) +push_iproto_constant_subnamespace( + struct lua_State *L, const char *subnamespace, + const struct iproto_constant *constants, int constants_len, + const char *strip_prefix) { + size_t prefix_len = 0; + if (strip_prefix != NULL) + prefix_len = strlen(strip_prefix); lua_createtable(L, 0, constants_len); for (int i = 0; i < constants_len; ++i) { - lua_pushinteger(L, constants[i].val); - lua_setfield(L, -2, constants[i].name); + const char *name = constants[i].name; + int value = constants[i].value; + if (strstr(name, "RESERVED")) + continue; + assert(prefix_len == 0 || + strncmp(name, strip_prefix, prefix_len) == 0); + lua_pushinteger(L, value); + lua_setfield(L, -2, name + prefix_len); } lua_setfield(L, -2, subnamespace); } /** - * Pushes IPROTO constants related to `IPROTO_FLAG` key onto Lua stack. + * Pushes IPROTO constants generated from `IPROTO_FLAGS` onto Lua stack. */ static void push_iproto_flag_constants(struct lua_State *L) { - const struct iproto_constant flags[] = { - {"COMMIT", IPROTO_FLAG_COMMIT}, - {"WAIT_SYNC", IPROTO_FLAG_WAIT_SYNC}, - {"WAIT_ACK", IPROTO_FLAG_WAIT_ACK}, - }; - push_iproto_constant_subnamespace(L, "flag", flags, lengthof(flags)); + push_iproto_constant_subnamespace( + L, "flag", iproto_flag_constants, iproto_flag_constants_size, + "IPROTO_FLAG_"); } /** - * Pushes IPROTO constants from `iproto_key` enumeration onto Lua stack. + * Pushes IPROTO constants generated from `IPROTO_KEYS` onto Lua stack. */ static void push_iproto_key_enum(struct lua_State *L) { - const struct iproto_constant keys[] = { - {"REQUEST_TYPE", IPROTO_REQUEST_TYPE}, - {"SYNC", IPROTO_SYNC}, - {"REPLICA_ID", IPROTO_REPLICA_ID}, - {"LSN", IPROTO_LSN}, - {"TIMESTAMP", IPROTO_TIMESTAMP}, - {"SCHEMA_VERSION", IPROTO_SCHEMA_VERSION}, - {"SERVER_VERSION", IPROTO_SERVER_VERSION}, - {"GROUP_ID", IPROTO_GROUP_ID}, - {"TSN", IPROTO_TSN}, - {"FLAGS", IPROTO_FLAGS}, - {"STREAM_ID", IPROTO_STREAM_ID}, - {"SPACE_ID", IPROTO_SPACE_ID}, - {"INDEX_ID", IPROTO_INDEX_ID}, - {"LIMIT", IPROTO_LIMIT}, - {"OFFSET", IPROTO_OFFSET}, - {"ITERATOR", IPROTO_ITERATOR}, - {"INDEX_BASE", IPROTO_INDEX_BASE}, - {"FETCH_POSITION", IPROTO_FETCH_POSITION}, - {"KEY", IPROTO_KEY}, - {"TUPLE", IPROTO_TUPLE}, - {"FUNCTION_NAME", IPROTO_FUNCTION_NAME}, - {"USER_NAME", IPROTO_USER_NAME}, - {"INSTANCE_UUID", IPROTO_INSTANCE_UUID}, - {"REPLICASET_UUID", IPROTO_REPLICASET_UUID}, - {"VCLOCK", IPROTO_VCLOCK}, - {"EXPR", IPROTO_EXPR}, - {"OPS", IPROTO_OPS}, - {"BALLOT", IPROTO_BALLOT}, - {"TUPLE_META", IPROTO_TUPLE_META}, - {"OPTIONS", IPROTO_OPTIONS}, - {"OLD_TUPLE", IPROTO_OLD_TUPLE}, - {"NEW_TUPLE", IPROTO_NEW_TUPLE}, - {"IPROTO_AFTER_POSITION", IPROTO_AFTER_POSITION}, - {"IPROTO_AFTER_TUPLE", IPROTO_AFTER_TUPLE}, - {"DATA", IPROTO_DATA}, - {"ERROR_24", IPROTO_ERROR_24}, - {"METADATA", IPROTO_METADATA}, - {"BIND_METADATA", IPROTO_BIND_METADATA}, - {"BIND_COUNT", IPROTO_BIND_COUNT}, - {"IPROTO_POSITION", IPROTO_POSITION}, - {"SQL_TEXT", IPROTO_SQL_TEXT}, - {"SQL_BIND", IPROTO_SQL_BIND}, - {"SQL_INFO", IPROTO_SQL_INFO}, - {"STMT_ID", IPROTO_STMT_ID}, - {"REPLICA_ANON", IPROTO_REPLICA_ANON}, - {"ID_FILTER", IPROTO_ID_FILTER}, - {"ERROR", IPROTO_ERROR}, - {"TERM", IPROTO_TERM}, - {"VERSION", IPROTO_VERSION}, - {"FEATURES", IPROTO_FEATURES}, - {"TIMEOUT", IPROTO_TIMEOUT}, - {"EVENT_KEY", IPROTO_EVENT_KEY}, - {"EVENT_DATA", IPROTO_EVENT_DATA}, - {"TXN_ISOLATION", IPROTO_TXN_ISOLATION}, - {"VCLOCK_SYNC", IPROTO_VCLOCK_SYNC}, - }; - push_iproto_constant_subnamespace(L, "key", keys, lengthof(keys)); - for (size_t i = 0; i < lengthof(keys); ++i) { - size_t len = strlen(keys[i].name); - char *lowercase = strtolowerdup(keys[i].name); + const char *prefix = "IPROTO_"; + size_t prefix_size = strlen(prefix); + push_iproto_constant_subnamespace( + L, "key", iproto_key_constants, iproto_key_constants_size, + prefix); + for (size_t i = 0; i < iproto_key_constants_size; ++i) { + const char *name = iproto_key_constants[i].name + prefix_size; + size_t len = strlen(name); + char *lowercase = strtolowerdup(name); struct mh_strnu32_node_t translation = { .str = lowercase, .len = len, .hash = lua_hash(lowercase, len), - .val = keys[i].val, + .val = iproto_key_constants[i].value, }; mh_strnu32_put(iproto_key_translation, &translation, NULL, NULL); - translation.str = xstrdup(keys[i].name); + translation.str = xstrdup(name); translation.hash = lua_hash(translation.str, len); mh_strnu32_put(iproto_key_translation, &translation, NULL, NULL); @@ -155,113 +96,47 @@ push_iproto_key_enum(struct lua_State *L) } /** - * Pushes IPROTO constants from `iproto_metadata_key` enumeration onto Lua - * stack. + * Pushes IPROTO constants generated from `IPROTO_METADATA_KEYS` onto Lua stack. */ static void push_iproto_metadata_key_enum(struct lua_State *L) { - const struct iproto_constant metadata_keys[] = { - {"NAME", IPROTO_FIELD_NAME}, - {"TYPE", IPROTO_FIELD_TYPE}, - {"COLL", IPROTO_FIELD_COLL}, - {"IS_NULLABLE", IPROTO_FIELD_IS_NULLABLE}, - {"IS_AUTOINCREMENT", IPROTO_FIELD_IS_AUTOINCREMENT}, - {"SPAN", IPROTO_FIELD_SPAN}, - }; - push_iproto_constant_subnamespace(L, "metadata_key", metadata_keys, - lengthof(metadata_keys)); + push_iproto_constant_subnamespace( + L, "metadata_key", iproto_metadata_key_constants, + iproto_metadata_key_constants_size, "IPROTO_FIELD_"); } /** - * Pushes IPROTO constants from `iproto_ballot_key` enumeration onto Lua stack. + * Pushes IPROTO constants generated from `IPROTO_BALLOT_KEYS` onto Lua stack. */ static void push_iproto_ballot_key_enum(struct lua_State *L) { - const struct iproto_constant ballot_keys[] = { - {"IS_RO_CFG", IPROTO_BALLOT_IS_RO_CFG}, - {"VCLOCK", IPROTO_BALLOT_VCLOCK}, - {"GC_VCLOCK", IPROTO_BALLOT_GC_VCLOCK}, - {"IS_RO", IPROTO_BALLOT_IS_RO}, - {"IS_ANON", IPROTO_BALLOT_IS_ANON}, - {"IS_BOOTED", IPROTO_BALLOT_IS_BOOTED}, - {"CAN_LEAD", IPROTO_BALLOT_CAN_LEAD}, - {"BOOTSTRAP_LEADER_UUID", - IPROTO_BALLOT_BOOTSTRAP_LEADER_UUID}, - {"REGISTERED_REPLICA_UUIDS", - IPROTO_BALLOT_REGISTERED_REPLICA_UUIDS}, - }; - push_iproto_constant_subnamespace(L, "ballot_key", ballot_keys, - lengthof(ballot_keys)); + push_iproto_constant_subnamespace( + L, "ballot_key", iproto_ballot_key_constants, + iproto_ballot_key_constants_size, "IPROTO_BALLOT_"); } /** - * Pushes IPROTO constants from `iproto_type` enumeration onto Lua stack. + * Pushes IPROTO constants generated from `IPROTO_TYPES` onto Lua stack. */ static void push_iproto_type_enum(struct lua_State *L) { - const struct iproto_constant types[] = { - {"OK", IPROTO_OK}, - {"SELECT", IPROTO_SELECT}, - {"INSERT", IPROTO_INSERT}, - {"REPLACE", IPROTO_REPLACE}, - {"UPDATE", IPROTO_UPDATE}, - {"DELETE", IPROTO_DELETE}, - {"CALL_16", IPROTO_CALL_16}, - {"AUTH", IPROTO_AUTH}, - {"EVAL", IPROTO_EVAL}, - {"UPSERT", IPROTO_UPSERT}, - {"CALL", IPROTO_CALL}, - {"EXECUTE", IPROTO_EXECUTE}, - {"NOP", IPROTO_NOP}, - {"PREPARE", IPROTO_PREPARE}, - {"BEGIN", IPROTO_BEGIN}, - {"COMMIT", IPROTO_COMMIT}, - {"ROLLBACK", IPROTO_ROLLBACK}, - {"RAFT", IPROTO_RAFT}, - {"RAFT_PROMOTE", IPROTO_RAFT_PROMOTE}, - {"RAFT_DEMOTE", IPROTO_RAFT_DEMOTE}, - {"RAFT_CONFIRM", IPROTO_RAFT_CONFIRM}, - {"RAFT_ROLLBACK", IPROTO_RAFT_ROLLBACK}, - {"PING", IPROTO_PING}, - {"JOIN", IPROTO_JOIN}, - {"SUBSCRIBE", IPROTO_SUBSCRIBE}, - {"VOTE_DEPRECATED", IPROTO_VOTE_DEPRECATED}, - {"VOTE", IPROTO_VOTE}, - {"FETCH_SNAPSHOT", IPROTO_FETCH_SNAPSHOT}, - {"REGISTER", IPROTO_REGISTER}, - {"JOIN_META", IPROTO_JOIN_META}, - {"JOIN_SNAPSHOT", IPROTO_JOIN_SNAPSHOT}, - {"ID", IPROTO_ID}, - {"WATCH", IPROTO_WATCH}, - {"UNWATCH", IPROTO_UNWATCH}, - {"EVENT", IPROTO_EVENT}, - {"CHUNK", IPROTO_CHUNK}, - {"TYPE_ERROR", IPROTO_TYPE_ERROR}, - {"UNKNOWN", IPROTO_UNKNOWN}, - }; - push_iproto_constant_subnamespace(L, "type", types, - lengthof(types)); + push_iproto_constant_subnamespace( + L, "type", iproto_type_constants, iproto_type_constants_size, + "IPROTO_"); } /** - * Pushes IPROTO constants from `iproto_raft_keys` enumeration onto Lua stack. + * Pushes IPROTO constants generated from `IPROTO_RAFT_KEYS` onto Lua stack. */ static void push_iproto_raft_keys_enum(struct lua_State *L) { - const struct iproto_constant raft_keys[] = { - {"TERM", IPROTO_RAFT_TERM}, - {"VOTE", IPROTO_RAFT_VOTE}, - {"STATE", IPROTO_RAFT_STATE}, - {"VCLOCK", IPROTO_RAFT_VCLOCK}, - {"LEADER_ID", IPROTO_RAFT_LEADER_ID}, - {"IS_LEADER_SEEN", IPROTO_RAFT_IS_LEADER_SEEN}, - }; - push_iproto_constant_subnamespace(L, "raft_key", raft_keys, - lengthof(raft_keys)); + push_iproto_constant_subnamespace( + L, "raft_key", iproto_raft_keys_constants, + iproto_raft_keys_constants_size, "IPROTO_RAFT_"); } /** @@ -287,23 +162,23 @@ push_iproto_protocol_features(struct lua_State *L) lua_pushinteger(L, IPROTO_CURRENT_VERSION); lua_setfield(L, -2, "protocol_version"); - const struct iproto_constant features[] = { - {"streams", IPROTO_FEATURE_STREAMS}, - {"transactions", IPROTO_FEATURE_TRANSACTIONS}, - {"error_extension", IPROTO_FEATURE_ERROR_EXTENSION}, - {"watchers", IPROTO_FEATURE_WATCHERS}, - {"pagination", IPROTO_FEATURE_PAGINATION}, - }; - - lua_createtable(L, 0, lengthof(features)); - for (size_t i = 0; i < lengthof(features); ++i) { + const char *prefix = "IPROTO_FEATURE_"; + size_t prefix_len = strlen(prefix); + for (size_t i = 0; i < 2; ++i) + lua_createtable(L, 0, iproto_feature_id_constants_size); + for (size_t i = 0; i < iproto_feature_id_constants_size; ++i) { + struct iproto_constant constant = + iproto_feature_id_constants[i]; + assert(strncmp(prefix, constant.name, prefix_len) == 0); + char *name = strtolowerdup(constant.name + prefix_len); lua_pushboolean(L, true); - lua_setfield(L, -2, features[i].name); + lua_setfield(L, -2, name); + lua_pushinteger(L, iproto_feature_id_constants[i].value); + lua_setfield(L, -3, name); + free(name); } - lua_setfield(L, -2, "protocol_features"); - - push_iproto_constant_subnamespace(L, "feature", features, - lengthof(features)); + lua_setfield(L, -3, "protocol_features"); + lua_setfield(L, -2, "feature"); } /** diff --git a/test/box-luatest/gh_7894_export_iproto_constants_and_features_test.lua b/test/box-luatest/gh_7894_export_iproto_constants_and_features_test.lua index 33abeb8c94ae2385a893ff8994ba2a7ec72b5ba2..a300fc05e5b0cd02d05d101d473d6b7d5ec777d1 100644 --- a/test/box-luatest/gh_7894_export_iproto_constants_and_features_test.lua +++ b/test/box-luatest/gh_7894_export_iproto_constants_and_features_test.lua @@ -56,14 +56,14 @@ local reference_table = { OPTIONS = 0x2b, OLD_TUPLE = 0x2c, NEW_TUPLE = 0x2d, - IPROTO_AFTER_POSITION = 0x2e, - IPROTO_AFTER_TUPLE = 0x2f, + AFTER_POSITION = 0x2e, + AFTER_TUPLE = 0x2f, DATA = 0x30, ERROR_24 = 0x31, METADATA = 0x32, BIND_METADATA = 0x33, BIND_COUNT = 0x34, - IPROTO_POSITION = 0x35, + POSITION = 0x35, SQL_TEXT = 0x40, SQL_BIND = 0x41, SQL_INFO = 0x42, @@ -79,6 +79,7 @@ local reference_table = { EVENT_DATA = 0x58, TXN_ISOLATION = 0x59, VCLOCK_SYNC = 0x5a, + AUTH_TYPE = 0x5b, }, -- `iproto_metadata_key` enumeration.