Return a migrateCachedSocket containing a TCP socket connected with the * target instance, possibly returning a cached one. * * This function is responsible of sending errors to the client if a * connection can't be established. In this case -1 is returned. * Otherwise on success the socket is returned, and the caller should not * attempt to free it after usage. * * If the caller detects a
| 5391 | * should be called so that the connection will be created from scratch |
| 5392 | * the next time. */ |
| 5393 | migrateCachedSocket* migrateGetSocket(client *c, robj *host, robj *port, long timeout) { |
| 5394 | connection *conn; |
| 5395 | sds name = sdsempty(); |
| 5396 | migrateCachedSocket *cs; |
| 5397 | |
| 5398 | /* Check if we have an already cached socket for this ip:port pair. */ |
| 5399 | name = sdscatlen(name,ptrFromObj(host),sdslen(szFromObj(host))); |
| 5400 | name = sdscatlen(name,":",1); |
| 5401 | name = sdscatlen(name,ptrFromObj(port),sdslen(szFromObj(port))); |
| 5402 | cs = (migrateCachedSocket*)dictFetchValue(g_pserver->migrate_cached_sockets,name); |
| 5403 | if (cs) { |
| 5404 | sdsfree(name); |
| 5405 | cs->last_use_time = g_pserver->unixtime; |
| 5406 | return cs; |
| 5407 | } |
| 5408 | |
| 5409 | /* No cached socket, create one. */ |
| 5410 | if (dictSize(g_pserver->migrate_cached_sockets) == MIGRATE_SOCKET_CACHE_ITEMS) { |
| 5411 | /* Too many items, drop one at random. */ |
| 5412 | dictEntry *de = dictGetRandomKey(g_pserver->migrate_cached_sockets); |
| 5413 | cs = (migrateCachedSocket*)dictGetVal(de); |
| 5414 | connClose(cs->conn); |
| 5415 | zfree(cs); |
| 5416 | dictDelete(g_pserver->migrate_cached_sockets,dictGetKey(de)); |
| 5417 | } |
| 5418 | |
| 5419 | /* Create the socket */ |
| 5420 | conn = g_pserver->tls_cluster ? connCreateTLS() : connCreateSocket(); |
| 5421 | if (connBlockingConnect(conn, szFromObj(c->argv[1]), atoi(szFromObj(c->argv[2])), timeout) |
| 5422 | != C_OK) { |
| 5423 | addReplyError(c,"-IOERR error or timeout connecting to the client"); |
| 5424 | connClose(conn); |
| 5425 | sdsfree(name); |
| 5426 | return NULL; |
| 5427 | } |
| 5428 | connEnableTcpNoDelay(conn); |
| 5429 | |
| 5430 | /* Add to the cache and return it to the caller. */ |
| 5431 | cs = (migrateCachedSocket*)zmalloc(sizeof(*cs), MALLOC_LOCAL); |
| 5432 | cs->conn = conn; |
| 5433 | cs->last_dbid = -1; |
| 5434 | cs->last_use_time = g_pserver->unixtime; |
| 5435 | dictAdd(g_pserver->migrate_cached_sockets,name,cs); |
| 5436 | return cs; |
| 5437 | } |
| 5438 | |
| 5439 | /* Free a migrate cached connection. */ |
| 5440 | void migrateCloseSocket(robj *host, robj *port) { |
no test coverage detected