int del(int count) { acl::string key, val; acl::redis cmd(&cluster_); struct timeval last, now; gettimeofday(&last, NULL); int i; for (i = 0; i < count; i++) { key.format("key-%d-%d", acl_fiber_self(), i); acl::fiber_sem_guard guard(sem_); if (cmd.del_one(key) < 0) { printf("fiber-%d: del error: %s, key: %s\r\n", acl_fiber_self(), cmd.result_error(), key.c_str()); break; } cmd.clear(); ndel_++; } gettimeofday(&now, NULL); double spent = stamp_sub(&now, &last); printf("---del spent %.2f ms, count %d, speed: %.2f----\r\n", spent, i, (i * 1000) / (spent > 0 ? spent : 1)); return i; }
// 客户端退出过程 static void client_logout(user_client* client) { // 从客户端列表中删除 if (client->already_login()) remove_user(client); // 如果该客户端的读协程还在工作,则通知该读协程退出 if (client->is_reading()) { printf("%s(%d): user: %s, kill_reader\r\n", __FUNCTION__, __LINE__, client->get_name()); client->kill_reader(); } // 如果该客户端的写协程还在工作,则通知该写协程退出 if (client->is_waiting()) { printf("fiber-%d: %s(%d): user: %s, notify logout\r\n", acl_fiber_self(), __FUNCTION__, __LINE__, client->get_name()); client->notify(MT_LOGOUT); } // 如果该客户端的读、写协程都已经退出,则通知该客户端退出 if (!client->is_reading() && !client->is_waiting()) client->notify_exit(); }
static void echo_client(int fd) { char buf[8192]; int ret, i; const char *str = "hello world\r\n"; for (i = 0; i < __max_loop; i++) { if (write(fd, str, strlen(str)) <= 0) { printf("write error: %s\r\n", strerror(errno)); break; } if (!__read_data) { __total_count++; if (i % 10000 == 0) printf("fiber-%d: total %lld, curr %d\r\n", acl_fiber_self(), __total_count, i); if (__total_count % 10000 == 0) acl_fiber_yield(); continue; } ret = read(fd, buf, sizeof(buf)); if (ret <= 0) { printf("read error: %s\r\n", strerror(errno)); break; } __total_count++; } close(fd); }
static void fiber_reader(user_client* client) { acl::socket_stream& conn = client->get_stream(); conn.set_rw_timeout(0); if (client_login(client) == false) { client_logout(client); return; } printf("fiber-%d: user: %s login OK\r\n", acl_fiber_self(), client->get_name()); acl::string buf; int max_loop = client->get_max_loop(), i; for (i = 0; i < max_loop; ++i) { if (conn.gets(buf)) { if (i <= 1) printf("fiber-%d: gets->%s\r\n", acl_fiber_self(), buf.c_str()); __total_read++; continue; } printf("%s(%d): user: %s, gets error %s, fiber: %d\r\n", __FUNCTION__, __LINE__, client->get_name(), acl::last_serror(), acl_fiber_self()); break; } printf(">>%s(%d), user: %s, logout, loop: %d\r\n", __FUNCTION__, __LINE__, client->get_name(), i); client_logout(client); }
int set(int count) { acl::string key, val; acl::redis cmd(&cluster_); struct timeval last, now; gettimeofday(&last, NULL); int i; for (i = 0; i < count; i++) { key.format("key-%d-%d", acl_fiber_self(), i); val.format("val-%d-%d", acl_fiber_self(), i); acl::fiber_sem_guard guard(sem_); if (cmd.set(key, val) == false) { printf("fiber-%d: set error: %s, key: %s\r\n", acl_fiber_self(), cmd.result_error(), key.c_str()); break; } else if (i < 5) printf("fiber-%d: set ok, key: %s\r\n", acl_fiber_self(), key.c_str()); cmd.clear(); nset_++; } gettimeofday(&now, NULL); double spent = stamp_sub(&now, &last); printf("---set spent %.2f ms, count %d, speed: %.2f----\r\n", spent, i, (i * 1000) / (spent > 0 ? spent : 1)); return i; }
static void fiber_wait(ACL_FIBER *, void *ctx) { ACL_CHANNEL *chan = (ACL_CHANNEL *) ctx; unsigned long n = acl_channel_recvul(chan); printf("----fiber-%d: get n: %lu---\r\n", acl_fiber_self(), n); for (int i = 0; __workers[i] != NULL; i++) { printf("kill fiber-%d\r\n", acl_fiber_id(__workers[i])); acl_fiber_kill(__workers[i]); } printf("---- fiber schedul stopping now ----\r\n"); acl_fiber_schedule_stop(); }
static void run(const char* addr) { acl::socket_stream conn; if (conn.open(addr, __conn_timeout, __rw_timeout) == false) { printf("connect %s error %s\r\n", addr, acl::last_serror()); __total_error_clients++; return; } if (__ssl_conf != NULL && ssl_init(conn) == false) return; __total_clients++; printf("fiber-%d: connect %s ok, clients: %d, fd: %d\r\n", acl_fiber_self(), addr, __total_clients, conn.sock_handle()); acl::string buf; const char req[] = "hello world\r\n"; for (int i = 0; i < __max_loop; i++) { if (conn.write(req, sizeof(req) - 1) == -1) { printf("write error: %s\r\n", acl::last_serror()); break; } if (conn.gets(buf, false) == false) { printf("gets error: %s\r\n", acl::last_serror()); break; } buf.clear(); __total_count++; } printf("close one connection: %d, %s\r\n", conn.sock_handle(), acl::last_serror()); }
static void fiber_client(const char* addr, const char* user, const char* to, int loop) { acl::socket_stream conn; if (conn.open(addr, 0, 10) == false) { printf("connect %s error %s\r\n", addr, acl::last_serror()); } else { printf("fiber-%d, connect %s ok\r\n", acl_fiber_self(), addr); user_client* client = new user_client(conn, user, to, loop); go[=] { fiber_reader(client); }; client->wait_exit(); printf("--- client %s exit now ----\r\n", client->get_name()); delete client; } __cur_client--; if (__cur_client == 0) { printf("-----All fibers over!-----\r\n"); struct timeval end; gettimeofday(&end, NULL); double spent = stamp_sub(&end, &__begin); printf("---Total read: %d, spent: %.2f, speed: %.2f---\r\n", __total_read, spent, (1000 * __total_read) / (spent < 1 ? 1 : spent)); acl_fiber_schedule_stop(); } }
if (n == 0) return 0; if (pfd.revents & POLLIN) return 1; else return 0; } static void echo_client(ACL_FIBER *fiber acl_unused, void *ctx) { int *cfd = (int *) ctx; char buf[8192]; int ret; printf("client fiber-%d: fd: %d\r\n", acl_fiber_self(), *cfd); while (1) { if (__rw_timeout > 0) { ret = check_read(*cfd, 10000); if (ret < 0) break; if (ret == 0) continue; } ret = read(*cfd, buf, sizeof(buf)); if (ret == 0) { printf("read close by peer fd: %d, %s\r\n", *cfd, strerror(errno)); break;
static void fiber_reader(user_client* client) { acl::socket_stream& conn = client->get_stream(); conn.set_rw_timeout(5); if (client_login(client) == false) { client_logout(client); return; } printf("fiber-%d: user: %s login OK\r\n", acl_fiber_self(), client->get_name()); acl::string buf; const char* to = client->get_to(); acl::string msg; int max_loop = client->get_max_loop(), i = 0, n = 0; for (;;) { msg.format("chat|%s|hello world\r\n", to); if (conn.write(msg) != (int) msg.size()) { printf("fiber-%d: msg(%s) write error %s\r\n", acl_fiber_self(), msg.c_str(), acl::last_serror()); } if (conn.gets(buf)) { if (++i <= 1) printf("fiber-%d: gets->%s\r\n", acl_fiber_self(), buf.c_str()); n++; __total_read++; if (n == max_loop) break; continue; } printf("%s(%d): user: %s, gets error %s, fiber: %d\r\n", __FUNCTION__, __LINE__, client->get_name(), acl::last_serror(), acl_fiber_self()); if (client->existing()) { printf("----existing now----\r\n"); break; } if (errno == ETIMEDOUT) printf("ETIMEDOUT\r\n"); else if (errno == EAGAIN) printf("EAGAIN\r\n"); else { printf("gets error: %d, %s\r\n", errno, acl::last_serror()); break; } } printf(">>%s(%d), user: %s, logout, loop: %d, ngets: %d\r\n", __FUNCTION__, __LINE__, client->get_name(), i, n); client_logout(client); }
int fiber::self(void) { return acl_fiber_self(); }
#include "lib_acl.h" #include <stdio.h> #include <stdlib.h> #include "fiber/lib_fiber.h" static int __fibers_count = 10; static void fiber_main(ACL_FIBER *fiber acl_unused, void *ctx) { ACL_FIBER_SEM *sem = (ACL_FIBER_SEM *) ctx; int left; printf("fiber-%d begin to sem_wait\r\n", acl_fiber_self()); left = acl_fiber_sem_wait(sem); printf("fiber-%d sem_wait ok, left: %d\r\n", acl_fiber_self(), left); printf("fiber-%d begin sleep\r\n", acl_fiber_self()); acl_fiber_sleep(1); printf("fiber-%d wakeup\r\n", acl_fiber_self()); left = acl_fiber_sem_post(sem); printf("fiber-%d sem_post ok, left: %d\r\n", acl_fiber_self(), left); if (--__fibers_count == 0) { printf("--- All fibers Over ----\r\n"); acl_fiber_stop(); } } static void usage(const char *procname) {
static void fiber_reader(user_client* client) { acl::socket_stream& conn = client->get_stream(); conn.set_rw_timeout(0); client->set_reader(); client->set_reading(true); // 登入服务器 if (client_login(client) == false) { client->set_reading(false); printf("----------client_logout-------\r\n"); // 失败,则退出客户端 client_logout(client); printf("----__nreader: %d-----\r\n", --__nreader); return; } // 登入成功,则创建写协程用来向客户端发送消息 go_stack(STACK_SIZE) [&] { __nwriter++; fiber_writer(client); }; conn.set_rw_timeout(0); bool stop = false; acl::string buf; // 从客户端循环读取消息 while (true) { bool ret = conn.gets(buf); if (ret == false) { printf("%s(%d): user: %s, gets error %s, fiber: %d\r\n", __FUNCTION__, __LINE__, client->get_name(), acl::last_serror(), acl_fiber_self()); // 客户端退出 if (client->exiting()) { printf("----exiting now----\r\n"); break; } if (errno == ETIMEDOUT) { if (conn.write("ping\r\n") == -1) { printf("ping error\r\n"); break; } } else if (errno == EAGAIN) printf("EAGAIN\r\n"); else { printf("gets error: %d, %s\r\n", errno, acl::last_serror()); break; } continue; } if (buf.empty()) continue; // 分析客户端发送的消息,交由不同的处理过程 std::vector<acl::string>& tokens = buf.split2("|"); // 本客户端要求退出 if (tokens[0] == "quit" || tokens[0] == "exit") { conn.write("Bye!\r\n"); break; } // 本客户端发送聊天消息 else if (tokens[0] == "chat") { if (client_chat(client, tokens) == false) break; } // 本客户端踢出其它客户端 else if (tokens[0] == "kick") { if (client_kick(client, tokens) == false) break; } // 要求整个服务进程退出 else if (tokens[0] == "stop") { stop = true; break; } else printf("invalid data: %s, cmd: [%s]\r\n", buf.c_str(), tokens[0].c_str()); } printf(">>%s(%d), user: %s, logout\r\n", __FUNCTION__, __LINE__, client->get_name()); client->set_reading(false); // 退出客户端 client_logout(client); printf("----__nreader: %d-----\r\n", --__nreader); if (stop) { int dumy = 1; // 如果要停止服务,则通知监控协程 __chan_monitor.put(dumy); } }