| 111 | } |
| 112 | |
| 113 | socket_stream* tcp_keeper::peek(const char* addr, bool* hit /* = NULL */, |
| 114 | bool sync /* = false */) |
| 115 | { |
| 116 | bool found = false; |
| 117 | |
| 118 | if (addr == NULL || *addr == 0) { |
| 119 | logger_fatal("addr null, addr=%s", addr ? addr : "null"); |
| 120 | } |
| 121 | |
| 122 | // if the rtt from the given addr is short, we should just connect |
| 123 | // the addr directivly. |
| 124 | // in direct-connect mode, using the caller's thread or fiber running |
| 125 | // space to connect the server addr. |
| 126 | if (sync || direct(addr, found)) { |
| 127 | if (hit) { |
| 128 | *hit = false; |
| 129 | } |
| 130 | |
| 131 | const keeper_config& config = waiter_->get_config(); |
| 132 | |
| 133 | struct timeval begin; |
| 134 | gettimeofday(&begin, NULL); |
| 135 | socket_stream* conn = new socket_stream; |
| 136 | |
| 137 | if (!conn->open(addr, config.conn_timeo, config.rw_timeo)) { |
| 138 | delete conn; |
| 139 | remove(addr); |
| 140 | return NULL; |
| 141 | } |
| 142 | |
| 143 | struct timeval end; |
| 144 | gettimeofday(&end, NULL); |
| 145 | double cost = stamp_sub(end, begin); |
| 146 | |
| 147 | // if this rtt cost by this connecting process is long, we |
| 148 | // should remove the addr from the direct-connect set to |
| 149 | // avoid directivly connect in the next connect. |
| 150 | if (cost > rtt_min_) { |
| 151 | //printf("remove %s, cost=%.2f > %.2f\r\n", |
| 152 | // addr, cost, rtt_min_); |
| 153 | if (found) { |
| 154 | remove(addr); |
| 155 | } |
| 156 | } |
| 157 | return conn; |
| 158 | } |
| 159 | |
| 160 | // then, we should peek one connection to the given addr from |
| 161 | // the keeper connection pool. |
| 162 | // we create one connection request and push it to the task handler. |
| 163 | task_req task; |
| 164 | task.set_addr(addr); |
| 165 | |
| 166 | task.set_stamp(); |
| 167 | waiter_->add_task(&task); |
| 168 | socket_stream* conn = task.pop(); |
| 169 | if (hit) { |
| 170 | *hit = task.is_hit(); |
no test coverage detected