diff --git a/.gitignore b/.gitignore index 3b96d13..be3d730 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ src/tests/test_server_id_func src/tests/test_pipe src/tests/test_atomic src/tests/test_file_write_hole +src/tests/test_file_lock # other *.swp diff --git a/src/tests/Makefile b/src/tests/Makefile index 5603b50..2cca679 100644 --- a/src/tests/Makefile +++ b/src/tests/Makefile @@ -8,7 +8,7 @@ ALL_PRGS = test_allocator test_skiplist test_multi_skiplist test_mblock test_blo test_id_generator test_ini_parser test_char_convert test_char_convert_loader \ test_logger test_skiplist_set test_crc32 test_thourands_seperator test_sched_thread \ test_json_parser test_pthread_lock test_uniq_skiplist test_split_string \ - test_server_id_func test_pipe test_atomic test_file_write_hole + test_server_id_func test_pipe test_atomic test_file_write_hole test_file_lock all: $(ALL_PRGS) .c: diff --git a/src/tests/test_file_lock.c b/src/tests/test_file_lock.c new file mode 100644 index 0000000..adcf5b9 --- /dev/null +++ b/src/tests/test_file_lock.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fastcommon/logger.h" +#include "fastcommon/shared_func.h" + +static inline int get_lock_info(int fd, struct flock *lock) +{ + int result; + + memset(lock, 0, sizeof(struct flock)); + lock->l_whence = SEEK_SET; + lock->l_type = F_WRLCK; + lock->l_pid = getpid(); + do { + if ((result=fcntl(fd, F_GETLK, lock)) != 0) + { + result = errno != 0 ? errno : ENOMEM; + fprintf(stderr, "call fcntl fail, " + "errno: %d, error info: %s\n", + result, STRERROR(result)); + } + } while (result == EINTR); + + return result; +} + +int main(int argc, char *argv[]) +{ +#define SEEK_POS (2 * 1024) + char *filename; + int fd; + int result; + int sleep_seconds; + int n; + char buf[1024]; + struct flock lock; + + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + log_init(); + filename = argv[1]; + if (argc >= 3) { + sleep_seconds = atoi(argv[2]); + } else { + sleep_seconds = 1; + } + + fd = open(filename, O_RDWR | O_CREAT, 0644); + if (fd < 0) { + result = errno != 0 ? errno : EIO; + logError("file: "__FILE__", line: %d, " + "open file %s fail, " + "errno: %d, error info: %s", + __LINE__, filename, + result, STRERROR(result)); + return result; + } + + if (flock(fd, LOCK_EX) < 0) { + logError("file: "__FILE__", line: %d, " + "flock file %s fail, " + "errno: %d, error info: %s", __LINE__, + filename, errno, STRERROR(errno)); + return errno != 0 ? errno : EIO; + } + + do { + if (ftruncate(fd, 102400) < 0) { + logError("file: "__FILE__", line: %d, " + "ftruncate file %s fail, " + "errno: %d, error info: %s", __LINE__, + filename, errno, STRERROR(errno)); + result = errno != 0 ? errno : EIO; + break; + } + + if (lseek(fd, SEEK_POS, SEEK_SET) < 0) { + logError("file: "__FILE__", line: %d, " + "lseek file %s fail, " + "errno: %d, error info: %s", __LINE__, + filename, errno, STRERROR(errno)); + result = errno != 0 ? errno : EIO; + break; + } + + memset(buf, '\n', sizeof(buf)); + if ((n=write(fd, buf, sizeof(buf))) <= 0) { + logError("file: "__FILE__", line: %d, " + "write to file %s fail, " + "errno: %d, error info: %s", __LINE__, + filename, errno, STRERROR(errno)); + result = errno != 0 ? errno : EIO; + break; + } + result = 0; + logInfo("pid: %d, write bytes: %d", getpid(), n); + } while (0); + + sleep(sleep_seconds); + + if ((result=get_lock_info(fd, &lock)) == 0) { + logInfo("lock info: { type: %d, whence: %d, start: %"PRId64", " + "len: %"PRId64", pid: %d }", + lock.l_type, lock.l_whence, (int64_t)lock.l_start, + (int64_t)lock.l_len, lock.l_pid); + } + + if (flock(fd, LOCK_UN) < 0) { + logError("file: "__FILE__", line: %d, " + "unlock file %s fail, " + "errno: %d, error info: %s", __LINE__, + filename, errno, STRERROR(errno)); + return errno != 0 ? errno : EIO; + } + + if (result != 0) { + return result; + } + + if ((result=get_lock_info(fd, &lock)) == 0) { + logInfo("lock info: { type: %d, whence: %d, start: %"PRId64", " + "len: %"PRId64", pid: %d }", + lock.l_type, lock.l_whence, (int64_t)lock.l_start, + (int64_t)lock.l_len, lock.l_pid); + } + + + logInfo("pid: %d, before lock ...", getpid()); + if ((result=file_read_lock(fd)) != 0) { + logError("file: "__FILE__", line: %d, " + "lock file %s fail, " + "errno: %d, error info: %s", __LINE__, + filename, result, STRERROR(result)); + return result; + } + + if ((result=get_lock_info(fd, &lock)) == 0) { + logInfo("lock info: { type: %d, whence: %d, start: %"PRId64", " + "len: %"PRId64", pid: %d }", + lock.l_type, lock.l_whence, (int64_t)lock.l_start, + (int64_t)lock.l_len, lock.l_pid); + } + + + logInfo("pid: %d, after lock.", getpid()); + do { + if (lseek(fd, 0, SEEK_SET) < 0) { + result = errno != 0 ? errno : EIO; + logError("file: "__FILE__", line: %d, " + "lseek file %s fail, " + "errno: %d, error info: %s", __LINE__, + filename, result, STRERROR(result)); + break; + } + + if ((n=read(fd, buf, sizeof(buf))) <= 0) { + result = errno != 0 ? errno : EIO; + logError("file: "__FILE__", line: %d, " + "read from file %s fail, " + "errno: %d, error info: %s", __LINE__, + filename, result, STRERROR(result)); + break; + } + } while (0); + + sleep(sleep_seconds); + if ((result=file_unlock(fd)) != 0) { + logError("file: "__FILE__", line: %d, " + "unlock file %s fail, " + "errno: %d, error info: %s", __LINE__, + filename, result, STRERROR(result)); + } + + logInfo("pid: %d, read bytes: %d, 0 => 0x%02x, %d => 0x%02x\n", + getpid(), n, (unsigned char)buf[0], n - 1, (unsigned char)buf[n - 1]); + return result; +} diff --git a/src/tests/test_file_write_hole.c b/src/tests/test_file_write_hole.c index 0c508a3..cd96153 100644 --- a/src/tests/test_file_write_hole.c +++ b/src/tests/test_file_write_hole.c @@ -26,13 +26,16 @@ int main(int argc, char *argv[]) log_init(); filename = argv[1]; + /* if (access(filename, F_OK) == 0) { logError("file: "__FILE__", line: %d, " "file %s already exists", __LINE__, filename); return EEXIST; } + */ - fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644); + //fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644); + fd = open(filename, O_RDWR | O_CREAT, 0644); if (fd < 0) { result = errno != 0 ? errno : EIO; logError("file: "__FILE__", line: %d, " \ @@ -43,6 +46,14 @@ int main(int argc, char *argv[]) return result; } + if (ftruncate(fd, 102400) < 0) { + logError("file: "__FILE__", line: %d, " \ + "ftruncate file %s fail, " \ + "errno: %d, error info: %s", __LINE__, \ + filename, errno, STRERROR(errno)); + return errno != 0 ? errno : EIO; + } + if (lseek(fd, SEEK_POS, SEEK_SET) < 0) { logError("file: "__FILE__", line: %d, " \ "lseek file %s fail, " \