}
struct ResponseMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "Response";}
- static std::string Name() {return TableName() + "Meta";}
-
static int IndexClosure(lua_State* L) {
- const auto err = reinterpret_cast<const rgw_err*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto err = reinterpret_cast<const rgw_err*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const char* index = luaL_checkstring(L, 2);
} else if (strcasecmp(index, "Message") == 0) {
pushstring(L, err->message);
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
static int NewIndexClosure(lua_State* L) {
- auto err = reinterpret_cast<rgw_err*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ auto err = reinterpret_cast<rgw_err*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const char* index = luaL_checkstring(L, 2);
} else if (strcasecmp(index, "Message") == 0) {
err->message.assign(luaL_checkstring(L, 3));
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return NO_RETURNVAL;
}
};
struct QuotaMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "Quota";}
- static std::string Name() {return TableName() + "Meta";}
-
static int IndexClosure(lua_State* L) {
- const auto info = reinterpret_cast<RGWQuotaInfo*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto info = reinterpret_cast<RGWQuotaInfo*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const char* index = luaL_checkstring(L, 2);
} else if (strcasecmp(index, "Rounded") == 0) {
lua_pushboolean(L, !info->check_on_raw);
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
};
struct PlacementRuleMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "PlacementRule";}
- static std::string Name() {return TableName() + "Meta";}
-
static int IndexClosure(lua_State* L) {
- const auto rule = reinterpret_cast<rgw_placement_rule*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto rule = reinterpret_cast<rgw_placement_rule*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const char* index = luaL_checkstring(L, 2);
} else if (strcasecmp(index, "StorageClass") == 0) {
pushstring(L, rule->storage_class);
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
};
struct UserMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "User";}
- static std::string Name() {return TableName() + "Meta";}
-
static int IndexClosure(lua_State* L) {
- const auto user = reinterpret_cast<const rgw_user*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto user = reinterpret_cast<const rgw_user*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const char* index = luaL_checkstring(L, 2);
} else if (strcasecmp(index, "Id") == 0) {
pushstring(L, user->id);
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
};
struct TraceMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "Trace";}
- static std::string Name() {return TableName() + "Meta";}
-
static int IndexClosure(lua_State* L) {
- const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const char* index = luaL_checkstring(L, 2);
lua_pushlightuserdata(L, s);
lua_pushcclosure(L, AddEvent, ONE_UPVAL);
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
static int NewIndexClosure(lua_State* L) {
- const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const char* index = luaL_checkstring(L, 2);
if (strcasecmp(index, "Enable") == 0) {
s->trace_enabled = lua_toboolean(L, 3);
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return NO_RETURNVAL;
}
};
struct OwnerMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "Owner";}
- static std::string Name() {return TableName() + "Meta";}
-
static int IndexClosure(lua_State* L) {
- const auto owner = reinterpret_cast<ACLOwner*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto owner = reinterpret_cast<ACLOwner*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const char* index = luaL_checkstring(L, 2);
if (strcasecmp(index, "DisplayName") == 0) {
pushstring(L, owner->get_display_name());
} else if (strcasecmp(index, "User") == 0) {
- create_metatable<UserMetaTable>(L, false, &(owner->get_id()));
+ create_metatable<UserMetaTable>(L, name, index, false,
+ &(owner->get_id()));
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
};
struct BucketMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "Bucket";}
- static std::string Name() {return TableName() + "Meta";}
-
static int IndexClosure(lua_State* L) {
- const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const auto bucket = s->bucket.get();
const char* index = luaL_checkstring(L, 2);
} else if (strcasecmp(index, "MTime") == 0) {
pushtime(L, bucket->get_modification_time());
} else if (strcasecmp(index, "Quota") == 0) {
- create_metatable<QuotaMetaTable>(L, false, &(bucket->get_info().quota));
+ create_metatable<QuotaMetaTable>(L, name, index, false, &(bucket->get_info().quota));
} else if (strcasecmp(index, "PlacementRule") == 0) {
- create_metatable<PlacementRuleMetaTable>(L, false, &(bucket->get_info().placement_rule));
+ create_metatable<PlacementRuleMetaTable>(L, name, index, false, &(bucket->get_info().placement_rule));
} else if (strcasecmp(index, "User") == 0) {
- create_metatable<UserMetaTable>(L, false,
+ create_metatable<UserMetaTable>(L, name, index, false,
const_cast<rgw_user*>(&bucket->get_owner()->get_id()));
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
static int NewIndexClosure(lua_State* L) {
- const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const auto bucket = s->bucket.get();
const char* index = luaL_checkstring(L, 2);
return NO_RETURNVAL;
}
}
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
};
struct ObjectMetaTable : public EmptyMetaTable {
- static const std::string TableName() {return "Object";}
- static std::string Name() {return TableName() + "Meta";}
-
using Type = rgw::sal::Object;
static int IndexClosure(lua_State* L) {
- const auto obj = reinterpret_cast<const Type*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto obj = reinterpret_cast<const Type*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const char* index = luaL_checkstring(L, 2);
} else if (strcasecmp(index, "MTime") == 0) {
pushtime(L, obj->get_mtime());
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
};
struct GrantMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "Grant";}
- static std::string Name() {return TableName() + "Meta";}
-
static int IndexClosure(lua_State* L) {
- const auto grant = reinterpret_cast<ACLGrant*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto grant = reinterpret_cast<ACLGrant*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const char* index = luaL_checkstring(L, 2);
} else if (strcasecmp(index, "User") == 0) {
const auto id_ptr = grant->get_id();
if (id_ptr) {
- create_metatable<UserMetaTable>(L, false, const_cast<rgw_user*>(id_ptr));
+ create_metatable<UserMetaTable>(L, name, index, false,
+ const_cast<rgw_user*>(id_ptr));
} else {
lua_pushnil(L);
}
} else if (strcasecmp(index, "Referer") == 0) {
pushstring(L, grant->get_referer());
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
using Type = ACLGrantMap;
static int IndexClosure(lua_State* L) {
- const auto map = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto map = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const char* index = luaL_checkstring(L, 2);
if (it == map->end()) {
lua_pushnil(L);
} else {
- create_metatable<GrantMetaTable>(L, false, &(it->second));
+ create_metatable<GrantMetaTable>(L, name, index, false, &(it->second));
}
return ONE_RETURNVAL;
}
static int PairsClosure(lua_State* L) {
- auto map = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
- ceph_assert(map);
- lua_pushlightuserdata(L, map);
- lua_pushcclosure(L, next<Type, GrantMetaTable>, ONE_UPVAL); // push the "next()" function
- lua_pushnil(L); // indicate this is the first call
- // return next, nil
-
- return TWO_RETURNVALS;
+ return Pairs<Type, next<Type, GrantMetaTable>>(L);
}
static int LenClosure(lua_State* L) {
};
struct ACLMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "ACL";}
- static std::string Name() {return TableName() + "Meta";}
-
using Type = RGWAccessControlPolicy;
static int IndexClosure(lua_State* L) {
- const auto acl = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto acl = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
- const char* index = luaL_checkstring(L, 2);
+ const auto index = luaL_checkstring(L, 2);
if (strcasecmp(index, "Owner") == 0) {
- create_metatable<OwnerMetaTable>(L, false, &(acl->get_owner()));
+ create_metatable<OwnerMetaTable>(L, name, index, false,
+ &(acl->get_owner()));
} else if (strcasecmp(index, "Grants") == 0) {
- create_metatable<GrantsMetaTable>(L, false, &(acl->get_acl().get_grant_map()));
+ create_metatable<GrantsMetaTable>(L, name, index, false, &(acl->get_acl().get_grant_map()));
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
};
struct StatementsMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "Statements";}
- static std::string Name() {return TableName() + "Meta";}
-
using Type = std::vector<rgw::IAM::Statement>;
static std::string statement_to_string(const rgw::IAM::Statement& statement) {
}
static int IndexClosure(lua_State* L) {
- const auto statements = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ std::ignore = table_name_upvalue(L);
+ const auto statements = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
+ ceph_assert(statements);
const auto index = luaL_checkinteger(L, 2);
}
static int PairsClosure(lua_State* L) {
- auto statements = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
- ceph_assert(statements);
- lua_pushlightuserdata(L, statements);
- lua_pushcclosure(L, stateless_iter, ONE_UPVAL); // push the stateless iterator function
- lua_pushnil(L); // indicate this is the first call
- // return stateless_iter, nil
-
- return TWO_RETURNVALS;
+ return Pairs<Type, stateless_iter>(L);
}
static int stateless_iter(lua_State* L) {
- auto statements = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ std::ignore = table_name_upvalue(L);
+ auto statements = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
size_t next_it;
if (lua_isnil(L, -1)) {
next_it = 0;
};
struct PolicyMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "Policy";}
- static std::string Name() {return TableName() + "Meta";}
-
static int IndexClosure(lua_State* L) {
- const auto policy = reinterpret_cast<rgw::IAM::Policy*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto policy = reinterpret_cast<rgw::IAM::Policy*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
- const char* index = luaL_checkstring(L, 2);
+ const auto index = luaL_checkstring(L, 2);
if (strcasecmp(index, "Text") == 0) {
pushstring(L, policy->text);
pushstring(L, policy->id.get());
}
} else if (strcasecmp(index, "Statements") == 0) {
- create_metatable<StatementsMetaTable>(L, false, &(policy->statements));
+ create_metatable<StatementsMetaTable>(L, name, index, false, &(policy->statements));
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
};
struct PoliciesMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "Policies";}
- static std::string Name() {return TableName() + "Meta";}
-
using Type = std::vector<rgw::IAM::Policy>;
static int IndexClosure(lua_State* L) {
- const auto policies = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto policies = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const auto index = luaL_checkinteger(L, 2);
if (index >= (int)policies->size() || index < 0) {
lua_pushnil(L);
} else {
- create_metatable<PolicyMetaTable>(L, false, &((*policies)[index]));
+ create_metatable<PolicyMetaTable>(L, name, std::to_string(index),
+ false, &((*policies)[index]));
}
return ONE_RETURNVAL;
}
static int PairsClosure(lua_State* L) {
- auto policies = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
- ceph_assert(policies);
- lua_pushlightuserdata(L, policies);
- lua_pushcclosure(L, stateless_iter, ONE_UPVAL); // push the stateless iterator function
- lua_pushnil(L); // indicate this is the first call
- // return stateless_iter, nil
-
- return TWO_RETURNVALS;
+ return Pairs<Type, stateless_iter>(L);
}
static int stateless_iter(lua_State* L) {
- auto policies = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ auto policies = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
size_t next_it;
if (lua_isnil(L, -1)) {
next_it = 0;
// return nil, nil
} else {
lua_pushinteger(L, next_it);
- create_metatable<PolicyMetaTable>(L, false, &((*policies)[next_it]));
+ create_metatable<PolicyMetaTable>(L, name, std::to_string(next_it),
+ false, &((*policies)[next_it]));
// return key, value
}
};
struct HTTPMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "HTTP";}
- static std::string Name() {return TableName() + "Meta";}
-
static int IndexClosure(lua_State* L) {
- const auto info = reinterpret_cast<req_info*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto info = reinterpret_cast<req_info*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
- const char* index = luaL_checkstring(L, 2);
+ const auto index = luaL_checkstring(L, 2);
if (strcasecmp(index, "Parameters") == 0) {
- create_metatable<StringMapMetaTable<>>(L, false, &(info->args.get_params()));
+ create_metatable<StringMapMetaTable<>>(L, name, index, false, &(info->args.get_params()));
} else if (strcasecmp(index, "Resources") == 0) {
// TODO: add non-const api to get resources
- create_metatable<StringMapMetaTable<>>(L, false,
+ create_metatable<StringMapMetaTable<>>(L, name, index, false,
const_cast<std::map<std::string, std::string>*>(&(info->args.get_sub_resources())));
} else if (strcasecmp(index, "Metadata") == 0) {
- create_metatable<StringMapMetaTable<meta_map_t, StringMapWriteableNewIndex<meta_map_t>>>(L, false, &(info->x_meta_map));
+ create_metatable<StringMapMetaTable<meta_map_t, StringMapWriteableNewIndex<meta_map_t>>>(L, name, index,
+ false, &(info->x_meta_map));
} else if (strcasecmp(index, "Host") == 0) {
pushstring(L, info->host);
} else if (strcasecmp(index, "Method") == 0) {
} else if (strcasecmp(index, "StorageClass") == 0) {
pushstring(L, info->storage_class);
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
static int NewIndexClosure(lua_State* L) {
- auto info = reinterpret_cast<req_info*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ auto info = reinterpret_cast<req_info*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
- const char* index = luaL_checkstring(L, 2);
+ const auto index = luaL_checkstring(L, 2);
if (strcasecmp(index, "StorageClass") == 0) {
info->storage_class = luaL_checkstring(L, 3);
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return NO_RETURNVAL;
}
};
struct CopyFromMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "CopyFrom";}
- static std::string Name() {return TableName() + "Meta";}
-
static int IndexClosure(lua_State* L) {
- const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
- const char* index = luaL_checkstring(L, 2);
+ const auto index = luaL_checkstring(L, 2);
if (strcasecmp(index, "Tenant") == 0) {
pushstring(L, s->src_tenant_name);
} else if (strcasecmp(index, "Bucket") == 0) {
pushstring(L, s->src_bucket_name);
} else if (strcasecmp(index, "Object") == 0) {
- create_metatable<ObjectMetaTable>(L, false, s->src_object);
+ create_metatable<ObjectMetaTable>(L, name, index, false, s->src_object);
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
};
struct ZoneGroupMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "ZoneGroup";}
- static std::string Name() {return TableName() + "Meta";}
-
static int IndexClosure(lua_State* L) {
- const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
- const char* index = luaL_checkstring(L, 2);
+ const auto index = luaL_checkstring(L, 2);
if (strcasecmp(index, "Name") == 0) {
pushstring(L, s->zonegroup_name);
} else if (strcasecmp(index, "Endpoint") == 0) {
pushstring(L, s->zonegroup_endpoint);
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
};
struct RequestMetaTable : public EmptyMetaTable {
- static std::string TableName() {return "Request";}
- static std::string Name() {return TableName() + "Meta";}
-
- // __index closure that expect req_state to be captured
static int IndexClosure(lua_State* L) {
- const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
- const auto op_name = reinterpret_cast<const char*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
+ const auto op_name = reinterpret_cast<const char*>(lua_touserdata(L, lua_upvalueindex(THIRD_UPVAL)));
const char* index = luaL_checkstring(L, 2);
} else if (strcasecmp(index, "ContentLength") == 0) {
lua_pushinteger(L, s->content_length);
} else if (strcasecmp(index, "GenericAttributes") == 0) {
- create_metatable<StringMapMetaTable<>>(L, false, &(s->generic_attrs));
+ create_metatable<StringMapMetaTable<>>(L, name, index, false, &(s->generic_attrs));
} else if (strcasecmp(index, "Response") == 0) {
- create_metatable<ResponseMetaTable>(L, false, &(s->err));
+ create_metatable<ResponseMetaTable>(L, name, index, false, &(s->err));
} else if (strcasecmp(index, "SwiftAccountName") == 0) {
if (s->dialect == "swift") {
pushstring(L, s->account_name);
lua_pushnil(L);
}
} else if (strcasecmp(index, "Bucket") == 0) {
- create_metatable<BucketMetaTable>(L, false, s);
+ create_metatable<BucketMetaTable>(L, name, index, false, s);
} else if (strcasecmp(index, "Object") == 0) {
- create_metatable<ObjectMetaTable>(L, false, s->object);
+ create_metatable<ObjectMetaTable>(L, name, index, false, s->object);
} else if (strcasecmp(index, "CopyFrom") == 0) {
if (s->op_type == RGW_OP_COPY_OBJ) {
- create_metatable<CopyFromMetaTable>(L, false, s);
+ create_metatable<CopyFromMetaTable>(L, name, index, false, s);
} else {
lua_pushnil(L);
}
} else if (strcasecmp(index, "ObjectOwner") == 0) {
- create_metatable<OwnerMetaTable>(L, false, &(s->owner));
+ create_metatable<OwnerMetaTable>(L, name, index, false, &(s->owner));
} else if (strcasecmp(index, "ZoneGroup") == 0) {
- create_metatable<ZoneGroupMetaTable>(L, false, s);
+ create_metatable<ZoneGroupMetaTable>(L, name, index, false, s);
} else if (strcasecmp(index, "UserACL") == 0) {
- create_metatable<ACLMetaTable>(L, false, s->user_acl);
+ create_metatable<ACLMetaTable>(L, name, index, false, s->user_acl);
} else if (strcasecmp(index, "BucketACL") == 0) {
- create_metatable<ACLMetaTable>(L, false, s->bucket_acl);
+ create_metatable<ACLMetaTable>(L, name, index, false, s->bucket_acl);
} else if (strcasecmp(index, "ObjectACL") == 0) {
- create_metatable<ACLMetaTable>(L, false, s->object_acl);
+ create_metatable<ACLMetaTable>(L, name, index, false, s->object_acl);
} else if (strcasecmp(index, "Environment") == 0) {
- create_metatable<StringMapMetaTable<rgw::IAM::Environment>>(L, false, &(s->env));
+ create_metatable<StringMapMetaTable<rgw::IAM::Environment>>(L, name, index, false, &(s->env));
} else if (strcasecmp(index, "Policy") == 0) {
// TODO: create a wrapper to std::optional
if (!s->iam_policy) {
lua_pushnil(L);
} else {
- create_metatable<PolicyMetaTable>(L, false, s->iam_policy.get_ptr());
+ create_metatable<PolicyMetaTable>(L, name, index, false, s->iam_policy.get_ptr());
}
} else if (strcasecmp(index, "UserPolicies") == 0) {
- create_metatable<PoliciesMetaTable>(L, false, &(s->iam_user_policies));
+ create_metatable<PoliciesMetaTable>(L, name, index, false, &(s->iam_user_policies));
} else if (strcasecmp(index, "RGWId") == 0) {
pushstring(L, s->host_id);
} else if (strcasecmp(index, "HTTP") == 0) {
- create_metatable<HTTPMetaTable>(L, false, &(s->info));
+ create_metatable<HTTPMetaTable>(L, name, index, false, &(s->info));
} else if (strcasecmp(index, "Time") == 0) {
pushtime(L, s->time);
} else if (strcasecmp(index, "Dialect") == 0) {
} else if (strcasecmp(index, "TransactionId") == 0) {
pushstring(L, s->trans_id);
} else if (strcasecmp(index, "Tags") == 0) {
- create_metatable<StringMapMetaTable<RGWObjTags::tag_map_t>>(L, false, &(s->tagset.get_tags()));
+ create_metatable<StringMapMetaTable<RGWObjTags::tag_map_t>>(L, name, index, false, &(s->tagset.get_tags()));
} else if (strcasecmp(index, "User") == 0) {
if (!s->user) {
lua_pushnil(L);
} else {
- create_metatable<UserMetaTable>(L, false, const_cast<rgw_user*>(&(s->user->get_id())));
+ create_metatable<UserMetaTable>(L, name, index, false,
+ const_cast<rgw_user*>(&(s->user->get_id())));
}
} else if (strcasecmp(index, "Trace") == 0) {
- create_metatable<TraceMetaTable>(L, false, s);
+ create_metatable<TraceMetaTable>(L, name, index, false, s);
} else {
- return error_unknown_field(L, index, TableName());
+ return error_unknown_field(L, index, name);
}
return ONE_RETURNVAL;
}
};
void create_top_metatable(lua_State* L, req_state* s, const char* op_name) {
- create_metatable<RequestMetaTable>(L, true, s, const_cast<char*>(op_name));
- lua_getglobal(L, RequestMetaTable::TableName().c_str());
- ceph_assert(lua_istable(L, -1));
+ static const char* request_table_name = "Request";
+ create_metatable<RequestMetaTable>(L, "", request_table_name, true, s, const_cast<char*>(op_name));
+ const auto type = lua_getglobal(L, request_table_name);
+ ceph_assert(type == LUA_TTABLE);
}
int execute(
set_package_path(L, s->penv.lua.luarocks_path);
create_debug_action(L, s->cct);
-
- create_metatable<RequestMetaTable>(L, true, s, const_cast<char*>(op_name));
-
- lua_getglobal(L, RequestMetaTable::TableName().c_str());
- ceph_assert(lua_istable(L, -1));
+
+ create_top_metatable(L, s, const_cast<char*>(op_name));
// add the ops log action
pushstring(L, RequestLogAction);
lua_pushlightuserdata(L, op);
lua_pushcclosure(L, RequestLog, FOUR_UPVALS);
lua_rawset(L, -3);
-
+
if (s->penv.lua.background) {
s->penv.lua.background->create_background_metatable(L);
- lua_getglobal(L, rgw::lua::RGWTable::TableName().c_str());
- ceph_assert(lua_istable(L, -1));
}
// execute the lua script
constexpr auto TWO_RETURNVALS = 2;
constexpr auto THREE_RETURNVALS = 3;
constexpr auto FOUR_RETURNVALS = 4;
-// utility functions to create a metatable
+
+// create_metatable() is a utility functions to create a metatable
// and tie it to an unnamed table
//
-// add an __index method to it, to allow reading values
+// it add an __index method to it, to allow reading values
// if "readonly" parameter is set to "false", it will also add
// a __newindex method to it, to allow writing values
// if the "toplevel" parameter is set to "true", it will name the
// table as well as the metatable, this would allow direct access from
// the lua script.
+// the name of the metatable will be a fully qualified name, based on the names
+// of the metatables that contain it, separated by dots.
+// it also adds a __len and __pairs methods for iterable entities.
//
// The MetaTable is expected to be a class with the following members:
-// Name (static function returning the unique name of the metatable)
-// TableName (static function returning the unique name of the table - needed only for "toplevel" tables)
// Type (typename) - the type of the "upvalue" (the type that the meta table represent)
// IndexClosure (static function return "int" and accept "lua_State*")
// NewIndexClosure (static function return "int" and accept "lua_State*")
+// PairsClosure (static function return "int" and accept "lua_State*")
+// LenClosure (static function return "int" and accept "lua_State*")
+//
// e.g.
// struct MyStructMetaTable {
-// static std::string TableName() {
-// return "MyStruct";
-// }
//
// using Type = MyStruct;
//
// static int IndexClosure(lua_State* L) {
-// const auto value = reinterpret_cast<const Type*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+// const auto name = tatable_name_upvalue(L);
+// const auto value = reinterpret_cast<const Type*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
// ...
// }
// static int NewIndexClosure(lua_State* L) {
+// const auto name = table_name_upvalue(L);
// auto value = reinterpret_cast<Type*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
// ...
// }
// };
//
+// If the structs inherits from EmptyMetatable then the only function that needs
+// to be implemented is IndexClosure. The other functions are implemented in
+// the base class stating that the table is "readonly" and "not-iterable".
template<typename MetaTable, typename... Upvalues>
-void create_metatable(lua_State* L, bool toplevel, Upvalues... upvalues)
+void create_metatable(lua_State* L, std::string_view parent_name, std::string_view field_name,
+ bool toplevel, Upvalues... upvalues)
{
+ const std::string qualified_name(fmt::format("{}{}{}",
+ parent_name,
+ (parent_name.empty() ? "" : "."),
+ field_name));
constexpr auto upvals_size = sizeof...(upvalues);
const std::array<void*, upvals_size> upvalue_arr = {upvalues...};
// create table
// duplicate the table to make sure it remain in the stack
lua_pushvalue(L, -1);
// give table a name (in cae of "toplevel")
- lua_setglobal(L, MetaTable::TableName().c_str());
+ lua_setglobal(L, qualified_name.c_str());
+ }
+
+ // create/reuse metatable
+ const auto metatable_is_new = luaL_newmetatable(L, qualified_name.c_str());
+ if (!metatable_is_new) {
+ // tie metatable to table
+ lua_setmetatable(L, -2);
+ return;
}
- // create metatable
- [[maybe_unused]] const auto rc = luaL_newmetatable(L, MetaTable::Name().c_str());
+
const auto table_stack_pos = lua_gettop(L);
// add "index" closure to metatable
lua_pushliteral(L, "__index");
+ pushstring(L, qualified_name);
for (const auto upvalue : upvalue_arr) {
lua_pushlightuserdata(L, upvalue);
}
- lua_pushcclosure(L, MetaTable::IndexClosure, upvals_size);
+ lua_pushcclosure(L, MetaTable::IndexClosure, upvals_size+1);
lua_rawset(L, table_stack_pos);
// add "newindex" closure to metatable
lua_pushliteral(L, "__newindex");
+ pushstring(L, qualified_name);
for (const auto upvalue : upvalue_arr) {
lua_pushlightuserdata(L, upvalue);
}
- lua_pushcclosure(L, MetaTable::NewIndexClosure, upvals_size);
+ lua_pushcclosure(L, MetaTable::NewIndexClosure, upvals_size+1);
lua_rawset(L, table_stack_pos);
// add "pairs" closure to metatable
lua_pushliteral(L, "__pairs");
+ pushstring(L, qualified_name);
for (const auto upvalue : upvalue_arr) {
lua_pushlightuserdata(L, upvalue);
}
- lua_pushcclosure(L, MetaTable::PairsClosure, upvals_size);
+ lua_pushcclosure(L, MetaTable::PairsClosure, upvals_size+1);
lua_rawset(L, table_stack_pos);
// add "len" closure to metatable
for (const auto upvalue : upvalue_arr) {
lua_pushlightuserdata(L, upvalue);
}
+ // "name" is not needed at the "len" closure
lua_pushcclosure(L, MetaTable::LenClosure, upvals_size);
lua_rawset(L, table_stack_pos);
- // tie metatable and table
- ceph_assert(lua_gettop(L) == table_stack_pos);
+ // tie metatable to table
lua_setmetatable(L, -2);
}
template<typename MetaTable>
-void create_metatable(lua_State* L, bool toplevel, std::unique_ptr<typename MetaTable::Type>& ptr)
+void create_metatable(lua_State* L, const std::string_view parent_name, const std::string_view field_name,
+ bool toplevel, std::unique_ptr<typename MetaTable::Type>& ptr)
{
if (ptr) {
- create_metatable<MetaTable>(L, toplevel, reinterpret_cast<void*>(ptr.get()));
+ create_metatable<MetaTable>(L, parent_name, field_name, toplevel, reinterpret_cast<void*>(ptr.get()));
} else {
lua_pushnil(L);
}
}
-
// following struct may be used as a base class for other MetaTable classes
// note, however, this is not mandatory to use it as a base
struct EmptyMetaTable {
typedef int MetaTableClosure(lua_State* L);
+// get iterator name from table name
+inline std::string get_iterator_name(const std::string_view name) {
+ return fmt::format("{}.Iterator", name);
+}
+
+// the fully qualified name of the table is expected to be the 1st upvalue of the closure
+inline const char* table_name_upvalue(lua_State* L) {
+ const auto name = reinterpret_cast<const char*>(lua_tostring(L, lua_upvalueindex(FIRST_UPVAL)));
+ ceph_assert(name);
+ return name;
+}
+
// copy the input iterator into a new iterator with memory allocated as userdata
// - allow for string conversion of the iterator (into its key)
// - storing the iterator in the metadata table to be used for iterator invalidation handling
// - since we have only one iterator per map/table we don't allow for nested loops or another iterationn
// after breaking out of an iteration
template<typename MapType>
-typename MapType::iterator* create_iterator_metadata(lua_State* L, const typename MapType::iterator& start_it, const typename MapType::iterator& end_it) {
+typename MapType::iterator* create_iterator_metadata(lua_State* L, const std::string_view name,
+ const typename MapType::iterator& start_it, const typename MapType::iterator& end_it) {
using Iterator = typename MapType::iterator;
+ const std::string qualified_name = get_iterator_name(name);
// create metatable for userdata
// metatable is created before the userdata to save on allocation if the metatable already exists
- const auto metatable_is_new = luaL_newmetatable(L, typeid(typename MapType::key_type).name());
+ const auto metatable_is_new = luaL_newmetatable(L, qualified_name.c_str());
const auto metatable_pos = lua_gettop(L);
int userdata_pos;
Iterator* new_it = nullptr;
auto old_it = reinterpret_cast<typename MapType::iterator*>(lua_touserdata(L, -1));
// verify we are not mid-iteration
if (*old_it != end_it) {
- luaL_error(L, "Trying to iterate '%s' before previous iteration finished",
- typeid(typename MapType::key_type).name());
+ luaL_error(L, "Trying to iterate '%s' before previous iteration finished", name.data());
return nullptr;
}
// we use the same memory buffer
return new_it;
}
+// when a value of a table is erased while the table is being iterated
+// this function allows updating the stored iterator with a new valid one
template<typename MapType>
-void update_erased_iterator(lua_State* L, const typename MapType::iterator& old_it, const typename MapType::iterator& new_it) {
+void update_erased_iterator(lua_State* L, const std::string_view name, const typename MapType::iterator& old_it, const typename MapType::iterator& new_it) {
// a metatable exists for the iterator
- if (luaL_getmetatable(L, typeid(typename MapType::key_type).name()) != LUA_TNIL) {
+ if (luaL_getmetatable(L, get_iterator_name(name).c_str()) != LUA_TNIL) {
const auto metatable_pos = lua_gettop(L);
lua_pushliteral(L, "__iterator");
if (lua_rawget(L, metatable_pos) != LUA_TNIL) {
int StringMapWriteableNewIndex(lua_State* L) {
static_assert(std::is_constructible<typename MapType::key_type, const char*>());
static_assert(std::is_constructible<typename MapType::mapped_type, const char*>());
- const auto map = reinterpret_cast<MapType*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ const auto map = reinterpret_cast<MapType*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
ceph_assert(map);
const char* index = luaL_checkstring(L, 2);
// erase the element. since in lua: "t[index] = nil" is removing the entry at "t[index]"
if (const auto it = map->find(index); it != map->end()) {
// index was found
- update_erased_iterator<MapType>(L, it, map->erase(it));
+ update_erased_iterator<MapType>(L, name, it, map->erase(it));
}
}
template<typename MapType, typename ValueMetaType=void>
int next(lua_State* L) {
using Iterator = typename MapType::iterator;
- auto map = reinterpret_cast<MapType*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
+ const auto name = table_name_upvalue(L);
+ auto map = reinterpret_cast<MapType*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
ceph_assert(map);
Iterator* next_it = nullptr;
// pop the 2 nils
lua_pop(L, 2);
// create userdata
- next_it = create_iterator_metadata<MapType>(L, map->begin(), map->end());
+ next_it = create_iterator_metadata<MapType>(L, name, map->begin(), map->end());
} else {
next_it = reinterpret_cast<Iterator*>(lua_touserdata(L, 2));
- ceph_assert(next_it);
*next_it = std::next(*next_it);
}
+ ceph_assert(next_it);
if (*next_it == map->end()) {
// index of the last element was provided
std::visit([L](auto&& value) { pushvalue(L, value); }, value);
} else {
// as a metatable
- create_metatable<ValueMetaType>(L, false, &(value));
+ create_metatable<ValueMetaType>(L, name, (*next_it)->first,
+ false, &(value));
}
// return key, value
return TWO_RETURNVALS;
}
+// a generic "Pairs" utility function that could be used as the metatable's "PairsClosure" function
+template<typename MapType, MetaTableClosure Next=next<MapType>>
+int Pairs(lua_State* L) {
+ const auto name = table_name_upvalue(L);
+ auto map = reinterpret_cast<MapType*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
+ ceph_assert(map);
+ pushstring(L, name);
+ lua_pushlightuserdata(L, map);
+ lua_pushcclosure(L, Next, TWO_UPVALS); // push the "next()" function
+ lua_pushnil(L); // indicate this is the first call
+ // return next, nil
+
+ return TWO_RETURNVALS;
+}
+
+
template<typename MapType=std::map<std::string, std::string>,
MetaTableClosure NewIndex=EmptyMetaTable::NewIndexClosure>
struct StringMapMetaTable : public EmptyMetaTable {
-
- static std::string TableName() {return "StringMap";}
- static std::string Name() {return TableName() + "Meta";}
-
static int IndexClosure(lua_State* L) {
- const auto map = reinterpret_cast<MapType*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
- ceph_assert(map);
+ std::ignore = table_name_upvalue(L);
+ const auto map = reinterpret_cast<MapType*>(lua_touserdata(L, lua_upvalueindex(SECOND_UPVAL)));
const char* index = luaL_checkstring(L, 2);
}
static int PairsClosure(lua_State* L) {
- auto map = reinterpret_cast<MapType*>(lua_touserdata(L, lua_upvalueindex(FIRST_UPVAL)));
- ceph_assert(map);
- lua_pushlightuserdata(L, map);
- lua_pushcclosure(L, next<MapType>, ONE_UPVAL); // push the "next()" function
- lua_pushnil(L); // indicate this is the first call
- // return next, nil
-
- return TWO_RETURNVALS;
+ return Pairs<MapType>(L);
}
static int LenClosure(lua_State* L) {