Here's a simple example of a client that has a connection open to a server and tries to read data from it. After reading from the descriptor, the client goes off to do something else (possibly causing a delay), and then returns to read again.
During this window of delay, the server might have died and returned, in which case the initial connection to the server (that has died) is now stale.
But since the connection has been made HA-aware, and a recovery function has been associated with it, the connection is able to reestablish itself.
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <ha/cover.h> #define SERVER "/path/to/server" typedef struct handle { int nr; } Handle ; int recover_conn2(int oldfd, void *hdl) { int newfd; Handle *thdl; thdl = (Handle *)hdl; printf("recovering for fd %d inside function 2\n",oldfd); /* re-open the connection */ newfd = ha_reopen(oldfd, SERVER, O_RDONLY); /* perform any other kind of state re-construction */ (thdl->nr)++; return(newfd); } int recover_conn(int oldfd, void *hdl) { int newfd; Handle *thdl; thdl = (Handle *)hdl; printf("recovering for fd %d inside function\n",oldfd); /* re-open the connection */ newfd = ha_reopen(oldfd, SERVER, O_RDONLY); /* perform any other kind of state reconstruction */ (thdl->nr)++; return(newfd); } int main(int argc, char *argv[]) { int status; int fd; int fd2; int fd3; Handle hdl; char buf[80]; int i; hdl.nr = 0; /* open a connection and make it HA aware */ fd = ha_open(SERVER, O_RDONLY,recover_conn, (void *)&hdl, 0); if (fd < 0) { printf("could not open %s\n", SERVER); exit(-1); } printf("fd = %d\n",fd); /* Dup the FD. the copy will also be HA aware */ fd2 = ha_dup(fd); printf("dup-ped fd2 = %d\n",fd2); printf("before sleeping first time\n"); /* Go to sleep... Possibly the SERVER might die and return in this little time period. */ sleep(15); /* reading from dup-ped fd this should work just normally if SERVER has not died. But if the SERVER has died and returned, the initial read will fail, but the recovery function will be called, and it will re-establish the connection, and then re-establish the current file position and then re-issue the read call which should succeed now. */ printf("trying to read from %s using fd %d\n",SERVER, fd2); status = read(fd2,buf,30); if (status < 0) printf("error: %s\n",strerror(errno)); /* fd and fd2 are dup-ped fd's changing the recovery function for fd2 From this point forwards, the recovery (if at all) will performed using "recover_conn2" as the recovery function. */ status = ha_attach(fd2, recover_conn2, (void *)&hdl, HAREPLACERECOVERYFN); ha_close(fd); /* close fd */ /* open a new connection */ fd = open(SERVER, O_RDONLY); printf("New fd = %d\n",fd); /* make it HA aware. */ status = ha_attach(fd, recover_conn, (void *)&hdl, 0); printf("before sleeping again\n"); /* copy it again */ fd3 = ha_dup(fd); /* go to sleep...possibly another option for the server to fail. */ sleep(15); /* get rid of one of the fd's we still have a copy in fd3, which must have the recovery functions associated with it. */ ha_close(fd); printf("trying to read from %s using fd %d\n",SERVER, fd3); /* if it fails, the call will generate a call back to the recovery function "recover_conn" */ status = read(fd3,buf,30); if (status < 0) printf("error: %s\n",strerror(errno)); printf("trying to read from %s once more using fd %d\n",SERVER, fd2); /* if this call fails, recovery will be via the second function "recover_conn2", since we replaced the function for fd2. */ status = read(fd2,buf,30); if (status < 0) printf("error: %s\n",strerror(errno)); /* close the fd2, and detach it from the HA lib */ ha_close(fd2); /* finally print out our local statistics that we have been retaining along the way. */ printf("total recoveries, %d\n",hdl.nr); exit(0); }