Use table to cache Error number to string conversion.

zmq3.0
Robert G. Jakabosky 15 years ago
parent e16bc680f7
commit 09c13aa2fd

@ -18,26 +18,290 @@
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-- THE SOFTWARE.
-- E* error values.
meta_object "ZErrors" {
export_definitions {
-- Native 0MQ error codes.
"EFSM",
"ENOCOMPATPROTO",
"ETERM",
"EMTHREAD",
"EPERM", -- Operation not permitted
"ENOENT", -- No such file or directory
"ESRCH", -- No such process
"EINTR", -- Interrupted system call
"EIO", -- I/O error
"ENXIO", -- No such device or address
"E2BIG", -- Argument list too long
"ENOEXEC", -- Exec format error
"EBADF", -- Bad file number
"ECHILD", -- No child processes
"EAGAIN", -- Try again
"ENOMEM", -- Out of memory
"EACCES", -- Permission denied
"EFAULT", -- Bad address
"ENOTBLK", -- Block device required
"EBUSY", -- Device or resource busy
"EEXIST", -- File exists
"EXDEV", -- Cross-device link
"ENODEV", -- No such device
"ENOTDIR", -- Not a directory
"EISDIR", -- Is a directory
"EINVAL", -- Invalid argument
"ENFILE", -- File table overflow
"EMFILE", -- Too many open files
"ENOTTY", -- Not a typewriter
"ETXTBSY", -- Text file busy
"EFBIG", -- File too large
"ENOSPC", -- No space left on device
"ESPIPE", -- Illegal seek
"EROFS", -- Read-only file system
"EMLINK", -- Too many links
"EPIPE", -- Broken pipe
"EDOM", -- Math argument out of domain of func
"ERANGE", -- Math result not representable
"EDEADLK", -- Resource deadlock would occur
"EDEADLOCK", -- EDEADLK
"ENAMETOOLONG", -- File name too long
"ENOLCK", -- No record locks available
"ENOSYS", -- Function not implemented
"ENOTEMPTY", -- Directory not empty
"ELOOP", -- Too many symbolic links encountered
"EWOULDBLOCK", -- Operation would block
"ENOMSG", -- No message of desired type
"EIDRM", -- Identifier removed
"ECHRNG", -- Channel number out of range
"EL2NSYNC", -- Level 2 not synchronized
"EL3HLT", -- Level 3 halted
"EL3RST", -- Level 3 reset
"ELNRNG", -- Link number out of range
"EUNATCH", -- Protocol driver not attached
"ENOCSI", -- No CSI structure available
"EL2HLT", -- Level 2 halted
"EBADE", -- Invalid exchange
"EBADR", -- Invalid request descriptor
"EXFULL", -- Exchange full
"ENOANO", -- No anode
"EBADRQC", -- Invalid request code
"EBADSLT", -- Invalid slot
"EBFONT", -- Bad font file format
"ENOSTR", -- Device not a stream
"ENODATA", -- No data available
"ETIME", -- Timer expired
"ENOSR", -- Out of streams resources
"ENONET", -- Machine is not on the network
"ENOPKG", -- Package not installed
"EREMOTE", -- Object is remote
"ENOLINK", -- Link has been severed
"EADV", -- Advertise error
"ESRMNT", -- Srmount error
"ECOMM", -- Communication error on send
"EPROTO", -- Protocol error
"EMULTIHOP", -- Multihop attempted
"EDOTDOT", -- RFS specific error
"EBADMSG", -- Not a data message
"EOVERFLOW", -- Value too large for defined data type
"ENOTUNIQ", -- Name not unique on network
"EBADFD", -- File descriptor in bad state
"EREMCHG", -- Remote address changed
"ELIBACC", -- Can not access a needed shared library
"ELIBBAD", -- Accessing a corrupted shared library
"ELIBSCN", -- .lib section in a.out corrupted
"ELIBMAX", -- Attempting to link in too many shared libraries
"ELIBEXEC", -- Cannot exec a shared library directly
"EILSEQ", -- Illegal byte sequence
"ERESTART", -- Interrupted system call should be restarted
"ESTRPIPE", -- Streams pipe error
"EUSERS", -- Too many users
"ENOTSOCK", -- Socket operation on non-socket
"EDESTADDRREQ", -- Destination address required
"EMSGSIZE", -- Message too long
"EPROTOTYPE", -- Protocol wrong type for socket
"ENOPROTOOPT", -- Protocol not available
"EPROTONOSUPPORT", -- Protocol not supported
"ESOCKTNOSUPPORT", -- Socket type not supported
"EOPNOTSUPP", -- Operation not supported on transport endpoint
"EPFNOSUPPORT", -- Protocol family not supported
"EAFNOSUPPORT", -- Address family not supported by protocol
"EADDRINUSE", -- Address already in use
"EADDRNOTAVAIL", -- Cannot assign requested address
"ENETDOWN", -- Network is down
"ENETUNREACH", -- Network is unreachable
"ENETRESET", -- Network dropped connection because of reset
"ECONNABORTED", -- Software caused connection abort
"ECONNRESET", -- Connection reset by peer
"ENOBUFS", -- No buffer space available
"EISCONN", -- Transport endpoint is already connected
"ENOTCONN", -- Transport endpoint is not connected
"ESHUTDOWN", -- Cannot send after transport endpoint shutdown
"ETOOMANYREFS", -- Too many references: cannot splice
"ETIMEDOUT", -- Connection timed out
"ECONNREFUSED", -- Connection refused
"EHOSTDOWN", -- Host is down
"EHOSTUNREACH", -- No route to host
"EALREADY", -- Operation already in progress
"EINPROGRESS", -- Operation now in progress
"ESTALE", -- Stale NFS file handle
"EUCLEAN", -- Structure needs cleaning
"ENOTNAM", -- Not a XENIX named type file
"ENAVAIL", -- No XENIX semaphores available
"EISNAM", -- Is a named type file
"EREMOTEIO", -- Remote I/O error
"EDQUOT", -- Quota exceeded
"ENOMEDIUM", -- No medium found
"EMEDIUMTYPE", -- Wrong medium type
"ECANCELED", -- Operation Canceled
"ENOKEY", -- Required key not available
"EKEYEXPIRED", -- Key has expired
"EKEYREVOKED", -- Key has been revoked
"EKEYREJECTED", -- Key was rejected by service
-- for robust mutexes
"EOWNERDEAD", -- Owner died
"ENOTRECOVERABLE", -- State not recoverable
"ERFKILL", -- Operation not possible due to RF-kill
},
method "description" {
var_in{ "<any>", "err" },
var_out{ "const char *", "msg" },
c_source "pre" [[
int err_type;
int err_num = -1;
]],
c_source[[
err_type = lua_type(L, ${err::idx});
if(err_type == LUA_TSTRING) {
lua_pushvalue(L, ${err::idx});
lua_rawget(L, ${this::idx});
if(lua_isnumber(L, -1)) {
err_num = lua_tointeger(L, -1);
}
lua_pop(L, 1);
} else if(err_type == LUA_TNUMBER) {
err_num = lua_tointeger(L, ${err::idx});
} else {
return luaL_argerror(L, ${err::idx}, "expected string/number");
}
if(err_num < 0) {
lua_pushnil(L);
lua_pushliteral(L, "UNKNOWN ERROR");
return 2;
}
${msg} = strerror(err_num);
]],
},
method "__index" {
var_in{ "int", "err" },
var_out{ "const char *", "msg" },
c_source[[
switch(${err}) {
case EAGAIN:
${msg} = "timeout";
break;
case EINTR:
${msg} = "interrupted";
break;
#if defined(ETERM)
case ETERM:
${msg} = "closed";
break;
#endif
default:
${msg} = zmq_strerror(${err});
break;
}
lua_pushvalue(L, ${err::idx});
lua_pushstring(L, ${msg});
lua_rawset(L, ${this::idx});
]],
},
}
ffi_source "ffi_src" [[
-- get ZErrors table to map errno to error name.
local ZError_names = _M.ZErrors
local function get_zmq_strerror()
return ZError_names[C.zmq_errno()]
end
]]
ffi_source "ffi_src" [[
]]
c_source "extra_code" [[
static char *zmq_ZErrors_key = "zmq_ZErrors_key";
/*
* This wrapper function is to make the EAGAIN/ETERM error messages more like
* what is returned by LuaSocket.
*/
static const char *get_zmq_strerror() {
int err = zmq_errno();
switch(err) {
case EAGAIN:
return "timeout";
break;
case EINTR:
return "interrupted";
break;
#if defined(ETERM)
case ETERM:
return "closed";
break;
#endif
default:
break;
}
return zmq_strerror(err);
}
]]
c_source "module_init_src" [[
/* Cache reference to zmq.ZErrors table for errno->string convertion. */
lua_pushlightuserdata(L, zmq_ZErrors_key);
lua_getfield(L, -2, "ZErrors");
lua_rawset(L, LUA_REGISTRYINDEX);
]]
-- Convert ZMQ Error codes into strings.
--
-- This is an error code wrapper object, it converts C-style 'int' return error code
-- into Lua-style 'nil, "Error message"' return values.
--
error_code "ZMQ_Error" "int" {
ffi_cdef[[
typedef int ZMQ_Error;
]],
ffi_type = "int",
is_error_check = function(rec) return "(-1 == ${" .. rec.name .. "})" end,
ffi_is_error_check = function(rec) return "(-1 == ${" .. rec.name .. "})" end,
default = "0",
c_source [[
if(-1 == err) {
err_str = get_zmq_strerror();
/* get ZErrors table. */
lua_pushlightuserdata(L, zmq_ZErrors_key);
lua_rawget(L, LUA_REGISTRYINDEX);
/* convert zmq_errno to string. */
lua_rawgeti(L, -1, zmq_errno());
/* remove ZErrors table. */
lua_remove(L, -2);
if(!lua_isnil(L, -1)) {
/* found error. */
return;
}
/* Unknown error. */
lua_pop(L, 1);
err_str = "UNKNOWN ERROR";
}
]],
ffi_source [[
if(-1 == err) then
err_str = get_zmq_strerror();
err_str = ZError_names[C.zmq_errno()]
end
]],
}

@ -35,43 +35,6 @@ ffi_load {
Windows = "libzmq", -- lib name for on windows.
},
c_source[[
/*
* This wrapper function is to make the EAGAIN/ETERM error messages more like
* what is returned by LuaSocket.
*/
static const char *get_zmq_strerror() {
int err = zmq_errno();
switch(err) {
case EAGAIN:
return "timeout";
break;
case EINTR:
return "interrupted";
break;
#if defined(ETERM)
case ETERM:
return "closed";
break;
#endif
default:
break;
}
return zmq_strerror(err);
}
]],
-- export helper function 'get_zmq_strerror' to FFI code.
ffi_export_function "const char *" "get_zmq_strerror" "()",
ffi_source[[
local C_get_zmq_strerror = get_zmq_strerror
-- make nicer wrapper for exported error function.
local function get_zmq_strerror()
return ffi.string(C_get_zmq_strerror())
end
]],
--
-- Module constants
--

Loading…
Cancel
Save