int main() { char neterr[ANET_ERR_LEN]; struct epoll_event ev; int listenfd; if(!db.Open("mydb")){ cerr<<"db open failed:"<<endl; return 0; } signal(SIGPIPE, SIG_IGN); //ignore sigpipe to prevent server shut down thread_pool.Run(); if((listenfd = anetTcpServer(neterr, 9999, NULL)) == ANET_ERR){ fprintf(stderr, "%s\n", neterr); exit(1); } anetNonBlock(neterr, listenfd); if((epfd = epoll_create(MAX_CLIENTS)) < 0){ perror("epoll_create"); exit(1); } ev.events = EPOLLIN; ev.data.fd =listenfd; if(epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev)<0){ perror("epoll_ctl"); exit(1); } for(;;){ int nfds = epoll_wait(epfd, events, MAX_CLIENTS, -1); for(int i = 0; i < nfds; ++i) { int fd = events[i].data.fd; if(fd == listenfd) { struct sockaddr_in cliaddr; socklen_t addrlen = sizeof(cliaddr); int connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &addrlen); if(connfd < 0){ if(errno == ECONNABORTED) //connection aborted, ignore it continue; else if(errno == EAGAIN) //no connections are ready to be accepted continue; else{ //error happened in accept, report it perror("accept"); continue; } } fprintf(stderr, "a new connfd: %d\n", connfd); anetNonBlock(neterr, connfd); ev.events = EPOLLIN; ev.data.fd = connfd; if (epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev) < 0) { perror("epoll_ctl"); return -1; } clients[connfd].fd = connfd; nclients++; } else if(events[i].events & EPOLLIN) { int n; char* rbuf = clients[fd].readbuf; while ((n = read(fd, rbuf+clients[fd].rpos, MAX_BUFLEN-clients[fd].rpos)) > 0) clients[fd].rpos += n; if (n == 0) { //client has been closed fprintf(stderr, "client has been closed, so server also close it, fd=%d\n", fd); close(fd); nclients--; } if (n<0 && errno != EAGAIN) { perror("read"); close(fd); nclients--; } int res = handle_read_event(&clients[fd]); if(res<0){ //error happened fprintf(stderr, "bad command, res=%d\n", res); close(fd); nclients--; }else if(res>0){ //the command has been hand over to a background thread, nothing to do here }else{ //res == 0, needs more data, continue reading } } else if(events[i].events & EPOLLOUT) { char* wbuf = clients[fd].writebuf; int wend = clients[fd].wend; int n; while (wend>clients[fd].wpos && (n = write(fd, wbuf+clients[fd].wpos, wend-clients[fd].wpos)) > 0) clients[fd].wpos += n; if (n<0 && errno != EAGAIN) { perror("write"); close(fd); nclients--; } if(wend == clients[fd].wpos){ //write finished //no need to rest for next write cause read event handler will do it //register as read event clients[fd].reset_for_next_read(); //reset for read ev.data.fd=fd; ev.events=EPOLLIN; epoll_ctl(epfd,EPOLL_CTL_MOD,fd,&ev); } } else{ //impossible! } } } return 0; }
int main(int argc, char* argv[]) { const char* dbname; const char* verifykey = NULL; union { unsigned char buf[64]; uint256_t hash; }; std::vector<node_t> nodes; std::vector<node_t>::const_iterator it; int idx, cnt, pos; int mode = MODE_ROOT; char *ptr; DB* db; if(argc<2) { fprintf(stderr, "Usage: %s <dbname> [key=verifier key] [<position>|<hash>|root|dump|gendata]\n", argv[0]); return 0; } dbname = argv[1]; for(idx=2; idx<argc; ++idx) { if(!strncmp(argv[idx], "key=", 4)) { verifykey = argv[idx] + 4; } else if(!strcmp(argv[idx], "dump")) { mode = MODE_DUMP; } else if(!strcmp(argv[idx], "root")) { mode = MODE_ROOT; } else if(!strcmp(argv[idx], "gendata")) { mode = MODE_GENTESTDATA; } else if(sizeof(uint256_t)*2==strlen(argv[idx])) { if(!HexData(argv[idx], buf, sizeof(buf))) { fprintf(stderr, "Invalid hash value: %s\n", argv[idx]); return 0; } mode = MODE_HASH; } else if(argv[idx][0]>='0' && argv[idx][0]<='9') { pos = strtol(argv[idx], &ptr, 10); if(ptr && *ptr) { fprintf(stderr, "Invalid position value: %s\n", argv[idx]); return 0; } mode = MODE_POSITION; } else { fprintf(stderr, "Unknown option: %s\n", argv[idx]); return 0; } } if(MODE_GENTESTDATA==mode) { if(!GenTestData(dbname)) fprintf(stderr, "Error generating data\n"); } db = new DB(dbname, verifykey); if(!db->Open()) { fprintf(stderr, "Open DB failed\n"); delete(db); return 0; } switch(mode) { case MODE_HASH: if(db->GetNodes(hash, nodes)) { idx = 0; for(idx=0,it=nodes.begin(); idx<nodes.size(); idx+=2) { fprintf(stdout, "%d: ", idx/2); if(idx+1<nodes.size()) { ShowHex(it->hash, sizeof(it->hash), false); ++it; fprintf(stdout, " / "); } ShowHex(it->hash, sizeof(it->hash), true); ++it; } } else fprintf(stderr, "Hash not found\n"); break; case MODE_POSITION: if(db->GetNodes(pos, nodes)) { idx = 0; for(idx=0,it=nodes.begin(); idx<nodes.size(); idx+=2) { fprintf(stdout, "%d: ", idx/2); if(idx+1<nodes.size()) { ShowHex(it->hash, sizeof(it->hash), false); ++it; fprintf(stdout, " / "); } ShowHex(it->hash, sizeof(it->hash), true); ++it; } } else fprintf(stderr, "Error reading tree\n"); break; case MODE_ROOT: if(db->GetRoot(nodes)) { fprintf(stdout, "Root %ld: ", nodes[2].data.value); ShowHex(nodes[2].hash, sizeof(nodes[2].hash), true); fprintf(stdout, "Hashes: "); ShowHex(nodes[0].hash, sizeof(nodes[0].hash), false); fprintf(stdout, " / "); ShowHex(nodes[1].hash, sizeof(nodes[1].hash), true); } else fprintf(stderr, "Error reading tree\n"); break; case MODE_DUMP: if(!db->Dump()) fprintf(stderr, "Error reading tree\n"); break; } return 1; }