diff options
| author | ruki <[email protected]> | 2019-07-25 00:45:28 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2019-07-24 22:32:48 +0800 |
| commit | 6634524cfdccf13e50a6fdbf55678832c530f908 (patch) | |
| tree | adc9f642278243eef51b008855184b16dbe34f19 | |
| parent | 493817cfeca5b40401e99ee857a96b3defa81421 (diff) | |
add file lock and unlock
| -rw-r--r-- | core/src/xmake/io/file.h | 12 | ||||
| -rw-r--r-- | core/src/xmake/io/file_path.c | 31 | ||||
| -rw-r--r-- | core/src/xmake/io/filelock.h | 25 | ||||
| -rw-r--r-- | core/src/xmake/io/filelock___tostring.c | 2 | ||||
| -rw-r--r-- | core/src/xmake/io/filelock_close___gc.c | 11 | ||||
| -rw-r--r-- | core/src/xmake/io/filelock_lock.c | 72 | ||||
| -rw-r--r-- | core/src/xmake/io/filelock_path.c | 27 | ||||
| -rw-r--r-- | core/src/xmake/io/filelock_trylock.c | 72 | ||||
| -rw-r--r-- | core/src/xmake/io/filelock_unlock.c | 57 | ||||
| -rw-r--r-- | core/src/xmake/machine.c | 12 | ||||
| -rw-r--r-- | core/src/xmake/makefile | 3 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/io.lua | 27 |
12 files changed, 300 insertions, 51 deletions
diff --git a/core/src/xmake/io/file.h b/core/src/xmake/io/file.h index 28ecc77ae..69555b393 100644 --- a/core/src/xmake/io/file.h +++ b/core/src/xmake/io/file.h @@ -38,14 +38,13 @@ #define xm_io_file_is_tty(file) (!!((file)->type & XM_IO_FILE_FLAG_TTY)) #define xm_io_file_is_closed(file) (xm_io_file_is_closed_file(file) || xm_io_file_is_closed_std(file)) -#define xm_io_file_udata "XM_IO_FILE*" +// the file udata type +#define xm_io_file_udata "io._file*" -#define xm_io_file_return_success() \ - do \ - { \ - return 1; \ - } while (0) +// return file success +#define xm_io_file_return_success() do { return 1; } while (0) +// return file error with reason #define xm_io_file_return_error(lua, file, reason) \ do \ { \ @@ -54,6 +53,7 @@ return 2; \ } while (0) +// return file closed error #define xm_io_file_return_error_closed(lua) \ do \ { \ diff --git a/core/src/xmake/io/file_path.c b/core/src/xmake/io/file_path.c index 1fcdb752a..fab2b156b 100644 --- a/core/src/xmake/io/file_path.c +++ b/core/src/xmake/io/file_path.c @@ -14,45 +14,42 @@ * * Copyright (C) 2015 - 2019, TBOOX Open Source Group. * - * @author ruki - * @file filelock_path.c + * @author OpportunityLiu + * @file file_path.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ -#define TB_TRACE_MODULE_NAME "filelock_path" +#define TB_TRACE_MODULE_NAME "file_path" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ -#include "filelock.h" +#include "file.h" +#include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ -/* filelock:path() +/* file:path() */ -tb_int_t xm_io_filelock_path(lua_State* lua) +tb_int_t xm_io_file_path(lua_State* lua) { // check tb_assert_and_check_return_val(lua, 0); - // this lock has been closed? - xm_io_filelock_t* lock = xm_io_get_filelock(lua); - if (!lock->is_opened) - { - lua_pushnil(lua); - lua_pushliteral(lua, "file lock has been closed!"); - return 2; - } + // this file has been closed? + xm_io_file_t* file = xm_io_getfile(lua); + if (xm_io_file_is_closed(file)) + xm_io_file_return_error_closed(lua); else { - // return lock path - lua_pushstring(lua, lock->path); - return 1; + // return file path + lua_pushstring(lua, file->path); + xm_io_file_return_success(); } } diff --git a/core/src/xmake/io/filelock.h b/core/src/xmake/io/filelock.h index e7e3536e8..f3c2a8f43 100644 --- a/core/src/xmake/io/filelock.h +++ b/core/src/xmake/io/filelock.h @@ -29,7 +29,30 @@ /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ -#define xm_io_filelock_udata "XM_IO_FILE_LOCK*" + +// the file lock udata type +#define xm_io_filelock_udata "io._filelock*" + +// return lock success +#define xm_io_filelock_return_success() do { return 1; } while (0) + +// return lock error with reason +#define xm_io_filelock_return_error(lua, lock, reason) \ + do \ + { \ + lua_pushnil(lua); \ + lua_pushfstring(lua, "error: %s (%s)", reason, lock->name); \ + return 2; \ + } while (0) + +// return closed error +#define xm_io_filelock_return_error_closed(lua) \ + do \ + { \ + lua_pushnil(lua); \ + lua_pushliteral(lua, "error: file lock has been closed"); \ + return 2; \ + } while (0) /* ////////////////////////////////////////////////////////////////////////////////////// * types diff --git a/core/src/xmake/io/filelock___tostring.c b/core/src/xmake/io/filelock___tostring.c index 8002b9eb3..417484c36 100644 --- a/core/src/xmake/io/filelock___tostring.c +++ b/core/src/xmake/io/filelock___tostring.c @@ -45,6 +45,6 @@ tb_int_t xm_io_filelock___tostring(lua_State* lua) // get lock name as string xm_io_filelock_t* lock = xm_io_get_filelock(lua); lua_pushstring(lua, lock->name); - return 1; + xm_io_filelock_return_success(); } diff --git a/core/src/xmake/io/filelock_close___gc.c b/core/src/xmake/io/filelock_close___gc.c index cadc02299..a2f263100 100644 --- a/core/src/xmake/io/filelock_close___gc.c +++ b/core/src/xmake/io/filelock_close___gc.c @@ -46,14 +46,9 @@ static tb_int_t xm_io_filelock_close_impl(lua_State* lua, tb_bool_t allow_closed if (allow_closed_lock) { lua_pushboolean(lua, tb_true); - return 1; - } - else - { - lua_pushnil(lua); - lua_pushliteral(lua, "file lock has been closed"); - return 2; + xm_io_filelock_return_success(); } + else xm_io_filelock_return_error_closed(lua); } // check @@ -76,7 +71,7 @@ static tb_int_t xm_io_filelock_close_impl(lua_State* lua, tb_bool_t allow_closed // close ok lua_pushboolean(lua, tb_true); - return 1; + xm_io_filelock_return_success(); } /* ////////////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/xmake/io/filelock_lock.c b/core/src/xmake/io/filelock_lock.c new file mode 100644 index 000000000..638cdd4fb --- /dev/null +++ b/core/src/xmake/io/filelock_lock.c @@ -0,0 +1,72 @@ +/*!A cross-platform build utility based on Lua + * + * 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. + * + * Copyright (C) 2015 - 2019, TBOOX Open Source Group. + * + * @author ruki + * @file filelock_lock.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "filelock_lock" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "filelock.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ + +/* lock file + * + * exclusive lock: filelock:lock("/xxxx/filelock") + * exclusive lock: filelock:lock("/xxxx/filelock", "ex") + * shared lock: filelock:lock("/xxxx/filelock", "sh") + */ +tb_int_t xm_io_filelock_lock(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // get lock mode + tb_char_t const* modestr = luaL_optstring(lua, 2, "ex"); + tb_assert_and_check_return_val(modestr, 0); + + // this lock has been closed? + xm_io_filelock_t* lock = xm_io_get_filelock(lua); + if (!lock->is_opened) + xm_io_filelock_return_error_closed(lua); + else + { + // is exclusive mode? + tb_bool_t is_exclusive = tb_true; + if (!tb_strcmp(modestr, "sh")) is_exclusive = tb_false; + else if (tb_strcmp(modestr, "ex")) + xm_io_filelock_return_error(lua, lock, "invalid lock mode!"); + + // lock it + if (tb_filelock_enter(lock->lock_ref, is_exclusive? TB_FILELOCK_MODE_EX : TB_FILELOCK_MODE_SH)) + { + lua_pushboolean(lua, tb_true); + xm_io_filelock_return_success(); + } + else xm_io_filelock_return_error(lua, lock, "lock failed!"); + } +} diff --git a/core/src/xmake/io/filelock_path.c b/core/src/xmake/io/filelock_path.c index e4221b6b9..1ab0fe932 100644 --- a/core/src/xmake/io/filelock_path.c +++ b/core/src/xmake/io/filelock_path.c @@ -14,42 +14,41 @@ * * Copyright (C) 2015 - 2019, TBOOX Open Source Group. * - * @author OpportunityLiu - * @file file_path.c + * @author ruki + * @file filelock_path.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ -#define TB_TRACE_MODULE_NAME "file_path" +#define TB_TRACE_MODULE_NAME "filelock_path" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ -#include "file.h" -#include "prefix.h" +#include "filelock.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ -/* file:path() +/* lock:path() */ -tb_int_t xm_io_file_path(lua_State* lua) +tb_int_t xm_io_filelock_path(lua_State* lua) { // check tb_assert_and_check_return_val(lua, 0); - // this file has been closed? - xm_io_file_t* file = xm_io_getfile(lua); - if (xm_io_file_is_closed(file)) - xm_io_file_return_error_closed(lua); + // this lock has been closed? + xm_io_filelock_t* lock = xm_io_get_filelock(lua); + if (!lock->is_opened) + xm_io_filelock_return_error_closed(lua); else { - // return file path - lua_pushstring(lua, file->path); - return 1; + // return lock path + lua_pushstring(lua, lock->path); + xm_io_filelock_return_success(); } } diff --git a/core/src/xmake/io/filelock_trylock.c b/core/src/xmake/io/filelock_trylock.c new file mode 100644 index 000000000..4195b2312 --- /dev/null +++ b/core/src/xmake/io/filelock_trylock.c @@ -0,0 +1,72 @@ +/*!A cross-platform build utility based on Lua + * + * 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. + * + * Copyright (C) 2015 - 2019, TBOOX Open Source Group. + * + * @author ruki + * @file filelock_trylock.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "filelock_trylock" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "filelock.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ + +/* try to lock file + * + * exclusive lock: filelock:trylock("/xxxx/filelock") + * exclusive lock: filelock:trylock("/xxxx/filelock", "ex") + * shared lock: filelock:trylock("/xxxx/filelock", "sh") + */ +tb_int_t xm_io_filelock_trylock(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // get lock mode + tb_char_t const* modestr = luaL_optstring(lua, 2, "ex"); + tb_assert_and_check_return_val(modestr, 0); + + // this lock has been closed? + xm_io_filelock_t* lock = xm_io_get_filelock(lua); + if (!lock->is_opened) + xm_io_filelock_return_error_closed(lua); + else + { + // is exclusive mode? + tb_bool_t is_exclusive = tb_true; + if (!tb_strcmp(modestr, "sh")) is_exclusive = tb_false; + else if (tb_strcmp(modestr, "ex")) + xm_io_filelock_return_error(lua, lock, "invalid lock mode!"); + + // try to lock it + if (tb_filelock_enter_try(lock->lock_ref, is_exclusive? TB_FILELOCK_MODE_EX : TB_FILELOCK_MODE_SH)) + { + lua_pushboolean(lua, tb_true); + xm_io_filelock_return_success(); + } + else xm_io_filelock_return_error(lua, lock, "trylock failed!"); + } +} diff --git a/core/src/xmake/io/filelock_unlock.c b/core/src/xmake/io/filelock_unlock.c new file mode 100644 index 000000000..266aab205 --- /dev/null +++ b/core/src/xmake/io/filelock_unlock.c @@ -0,0 +1,57 @@ +/*!A cross-platform build utility based on Lua + * + * 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. + * + * Copyright (C) 2015 - 2019, TBOOX Open Source Group. + * + * @author ruki + * @file filelock_unlock.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "filelock_unlock" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "filelock.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ + +// filelock:unlock() +tb_int_t xm_io_filelock_unlock(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // this lock has been closed? + xm_io_filelock_t* lock = xm_io_get_filelock(lua); + if (!lock->is_opened) + xm_io_filelock_return_error_closed(lua); + else + { + // unlock it + if (tb_filelock_leave(lock->lock_ref)) + { + lua_pushboolean(lua, tb_true); + xm_io_filelock_return_success(); + } + else xm_io_filelock_return_error(lua, lock, "unlock failed!"); + } +} diff --git a/core/src/xmake/machine.c b/core/src/xmake/machine.c index 66bf45c8b..78bddbc2b 100644 --- a/core/src/xmake/machine.c +++ b/core/src/xmake/machine.c @@ -108,6 +108,9 @@ tb_int_t xm_io_file___gc(lua_State* lua); // the filelock functions tb_int_t xm_io_filelock_path(lua_State* lua); +tb_int_t xm_io_filelock_lock(lua_State* lua); +tb_int_t xm_io_filelock_unlock(lua_State* lua); +tb_int_t xm_io_filelock_trylock(lua_State* lua); tb_int_t xm_io_filelock_close(lua_State* lua); tb_int_t xm_io_filelock___gc(lua_State* lua); tb_int_t xm_io_filelock___tostring(lua_State* lua); @@ -254,6 +257,9 @@ static luaL_Reg const g_io_filelock_functions[] = { { "path", xm_io_filelock_path } , { "close", xm_io_filelock_close } +, { "lock", xm_io_filelock_lock } +, { "unlock", xm_io_filelock_unlock } +, { "trylock", xm_io_filelock_trylock } , { "__gc", xm_io_filelock___gc } , { "__tostring", xm_io_filelock___tostring } , { tb_null, tb_null } @@ -575,7 +581,7 @@ static tb_void_t xm_machine_register_metatable(xm_machine_t* machine, tb_char_t * * metatype module.metaname = metatable {__index = metatable, funcs ...} * - * e.g. XM_IO_FILE* io.file = metatable {__index = metatable, funcs ...} + * e.g. io._file* io._file = metatable {__index = metatable, funcs ...} */ luaL_newmetatable(machine->lua, metatype); // stack: {metatable}, {metatable} @@ -621,10 +627,10 @@ xm_machine_ref_t xm_machine_init() luaL_register(machine->lua, "io", g_io_functions); // bind io.file (metatable) functions - xm_machine_register_metatable(machine, "io", "_file", "XM_IO_FILE*", g_io_file_functions); + xm_machine_register_metatable(machine, "io", "_file", "io._file*", g_io_file_functions); // bind io.filelock (metatable) functions - xm_machine_register_metatable(machine, "io", "_filelock", "XM_IO_FILE_LOCK*", g_io_filelock_functions); + xm_machine_register_metatable(machine, "io", "_filelock", "io._filelock*", g_io_filelock_functions); // add stdin, stdout, stderr to io xm_io_std(machine->lua); diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index ad3ddaad2..89500e727 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -54,6 +54,9 @@ xmake_C_FILES += \ io/file_seek \ io/file_write \ io/filelock_path \ + io/filelock_lock \ + io/filelock_unlock \ + io/filelock_trylock \ io/filelock___tostring \ io/filelock_close___gc \ io/open \ diff --git a/xmake/core/sandbox/modules/io.lua b/xmake/core/sandbox/modules/io.lua index 87354c459..c4c1a63c8 100644 --- a/xmake/core/sandbox/modules/io.lua +++ b/xmake/core/sandbox/modules/io.lua @@ -28,8 +28,9 @@ local vformat = require("sandbox/modules/vformat") -- define module local sandbox_io = sandbox_io or {} local sandbox_io_file = sandbox_io._file or {} +local sandbox_io_filelock = sandbox_io._filelock or {} sandbox_io._file = sandbox_io_file -sandbox_io._filelock = io._filelock +sandbox_io._filelock = sandbox_io_filelock -- inherit some builtin interfaces sandbox_io.lines = io.lines @@ -58,6 +59,26 @@ if sandbox_io_file.__index ~= sandbox_io_file then sandbox_io_file.lines = io._file.lines end +-- inherit matatable of file lock +if sandbox_io_filelock.__index ~= sandbox_io_filelock then + sandbox_io_filelock.__index = sandbox_io_filelock + for k, v in pairs(io._filelock) do + if type(v) == "function" then + sandbox_io_filelock[k] = function(s, ...) + local result, err = v(s._LOCK, ...) + if result == nil and err ~= nil then + raise(err) + end + -- wrap to sandbox_filelock again + if result == s._LOCK then + result = s + end + return result + end + end + end +end + -- get file size function sandbox_io_file:size() -- __len on tables is scheduled to be supported in 5.2. @@ -133,6 +154,10 @@ function sandbox_io.openlock(filepath) if not lock then raise(errors) end + + -- bind metatable + lock = { _LOCK = lock } + setmetatable(lock, sandbox_io_filelock); return lock end |
