Ignore:
Timestamp:
Nov 25, 2016, 8:04:54 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.7

Location:
vendor/current/ctdb/server
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/ctdb/server/ctdb_control.c

    r988 r989  
    716716                return ctdb_control_db_transaction_cancel(ctdb, indata);
    717717
     718        case CTDB_CONTROL_DB_PULL:
     719                CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_pulldb_ext));
     720                return ctdb_control_db_pull(ctdb, c, indata, outdata);
     721
     722        case CTDB_CONTROL_DB_PUSH_START:
     723                CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_pulldb_ext));
     724                return ctdb_control_db_push_start(ctdb, indata);
     725
     726        case CTDB_CONTROL_DB_PUSH_CONFIRM:
     727                CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
     728                return ctdb_control_db_push_confirm(ctdb, indata, outdata);
     729
    718730        default:
    719731                DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode));
  • vendor/current/ctdb/server/ctdb_daemon.c

    r988 r989  
    4444#include "common/common.h"
    4545#include "common/logging.h"
     46#include "common/pidfile.h"
    4647
    4748struct ctdb_client_pid_list {
     
    5354
    5455const char *ctdbd_pidfile = NULL;
     56static struct pidfile_context *ctdbd_pidfile_ctx = NULL;
    5557
    5658static void daemon_incoming_packet(void *, struct ctdb_req_header *);
     
    984986{
    985987        struct sockaddr_un addr;
     988        int ret;
    986989
    987990        ctdb->daemon.sd = socket(AF_UNIX, SOCK_STREAM, 0);
     
    994997        strncpy(addr.sun_path, ctdb->daemon.name, sizeof(addr.sun_path)-1);
    995998
    996         /* First check if an old ctdbd might be running */
    997         if (connect(ctdb->daemon.sd,
    998                     (struct sockaddr *)&addr, sizeof(addr)) == 0) {
    999                 DEBUG(DEBUG_CRIT,
    1000                       ("Something is already listening on ctdb socket '%s'\n",
    1001                        ctdb->daemon.name));
    1002                 goto failed;
    1003         }
    1004 
    1005999        /* Remove any old socket */
    1006         unlink(ctdb->daemon.name);
     1000        ret = unlink(ctdb->daemon.name);
     1001        if (ret == 0) {
     1002                DEBUG(DEBUG_WARNING,
     1003                      ("Removed stale socket %s\n", ctdb->daemon.name));
     1004        } else if (errno != ENOENT) {
     1005                DEBUG(DEBUG_ERR,
     1006                      ("Failed to remove stale socket %s\n", ctdb->daemon.name));
     1007                return -1;
     1008        }
    10071009
    10081010        set_close_on_exec(ctdb->daemon.sd);
     
    11281130static void ctdb_remove_pidfile(void)
    11291131{
    1130         /* Only the main ctdbd's PID matches the SID */
    1131         if (ctdbd_pidfile != NULL && getsid(0) == getpid()) {
    1132                 if (unlink(ctdbd_pidfile) == 0) {
    1133                         DEBUG(DEBUG_NOTICE, ("Removed PID file %s\n",
    1134                                              ctdbd_pidfile));
    1135                 } else {
    1136                         DEBUG(DEBUG_WARNING, ("Failed to Remove PID file %s\n",
    1137                                               ctdbd_pidfile));
    1138                 }
    1139         }
    1140 }
    1141 
    1142 static void ctdb_create_pidfile(pid_t pid)
     1132        TALLOC_FREE(ctdbd_pidfile_ctx);
     1133}
     1134
     1135static void ctdb_create_pidfile(TALLOC_CTX *mem_ctx)
    11431136{
    11441137        if (ctdbd_pidfile != NULL) {
    1145                 FILE *fp;
    1146 
    1147                 fp = fopen(ctdbd_pidfile, "w");
    1148                 if (fp == NULL) {
    1149                         DEBUG(DEBUG_ALERT,
    1150                               ("Failed to open PID file %s\n", ctdbd_pidfile));
     1138                int ret = pidfile_create(mem_ctx, ctdbd_pidfile,
     1139                                         &ctdbd_pidfile_ctx);
     1140                if (ret != 0) {
     1141                        DEBUG(DEBUG_ERR,
     1142                              ("Failed to create PID file %s\n",
     1143                              ctdbd_pidfile));
    11511144                        exit(11);
    11521145                }
    11531146
    1154                 fprintf(fp, "%d\n", pid);
    1155                 fclose(fp);
    11561147                DEBUG(DEBUG_NOTICE, ("Created PID file %s\n", ctdbd_pidfile));
    11571148                atexit(ctdb_remove_pidfile);
     
    12141205        int res, ret = -1;
    12151206        struct tevent_fd *fde;
     1207
     1208        if (do_fork && fork()) {
     1209                return 0;
     1210        }
     1211
     1212        if (do_fork) {
     1213                if (setsid() == -1) {
     1214                        ctdb_die(ctdb, "Failed to setsid()\n");
     1215                }
     1216                close(0);
     1217                if (open("/dev/null", O_RDONLY) != 0) {
     1218                        DEBUG(DEBUG_ALERT,(__location__ " Failed to setup stdin on /dev/null\n"));
     1219                        exit(11);
     1220                }
     1221        }
     1222        ignore_signal(SIGPIPE);
     1223        ignore_signal(SIGUSR1);
     1224
     1225        ctdb->ctdbd_pid = getpid();
     1226        DEBUG(DEBUG_ERR, ("Starting CTDBD (Version %s) as PID: %u\n",
     1227                          CTDB_VERSION_STRING, ctdb->ctdbd_pid));
     1228        ctdb_create_pidfile(ctdb);
    12161229
    12171230        /* create a unix domain stream socket to listen to */
     
    12221235        }
    12231236
    1224         if (do_fork && fork()) {
    1225                 return 0;
    1226         }
    1227 
    1228         tdb_reopen_all(false);
    1229 
    1230         if (do_fork) {
    1231                 if (setsid() == -1) {
    1232                         ctdb_die(ctdb, "Failed to setsid()\n");
    1233                 }
    1234                 close(0);
    1235                 if (open("/dev/null", O_RDONLY) != 0) {
    1236                         DEBUG(DEBUG_ALERT,(__location__ " Failed to setup stdin on /dev/null\n"));
    1237                         exit(11);
    1238                 }
    1239         }
    1240         ignore_signal(SIGPIPE);
    1241         ignore_signal(SIGUSR1);
    1242 
    1243         ctdb->ctdbd_pid = getpid();
    1244         DEBUG(DEBUG_ERR, ("Starting CTDBD (Version %s) as PID: %u\n",
    1245                           CTDB_VERSION_STRING, ctdb->ctdbd_pid));
    1246         ctdb_create_pidfile(ctdb->ctdbd_pid);
    1247 
    12481237        /* Make sure we log something when the daemon terminates.
    12491238         * This must be the first exit handler to run (so the last to
     
    12611250
    12621251        ctdb->ev = tevent_context_init(NULL);
     1252        if (ctdb->ev == NULL) {
     1253                DEBUG(DEBUG_ALERT,("tevent_context_init() failed\n"));
     1254                exit(1);
     1255        }
    12631256        tevent_loop_allow_nesting(ctdb->ev);
    12641257        tevent_set_trace_callback(ctdb->ev, ctdb_tevent_trace, ctdb);
     
    18461839        /* get a new event context */
    18471840        ctdb->ev = tevent_context_init(ctdb);
     1841        if (ctdb->ev == NULL) {
     1842                DEBUG(DEBUG_ALERT,("tevent_context_init() failed\n"));
     1843                exit(1);
     1844        }
    18481845        tevent_loop_allow_nesting(ctdb->ev);
    18491846
  • vendor/current/ctdb/server/ctdb_logging.c

    r988 r989  
    282282        /* We'll fail if stderr/stdout not already open; it's simpler. */
    283283        old_stdout = dup(STDOUT_FILENO);
     284        if (old_stdout < 0) {
     285                DEBUG(DEBUG_ERR, ("Failed to dup stdout for child logging\n"));
     286                return -1;
     287        }
    284288        old_stderr = dup(STDERR_FILENO);
    285         if (old_stdout < 0 || old_stderr < 0) {
    286                 DEBUG(DEBUG_ERR, ("Failed to dup stdout/stderr for child logging\n"));
     289        if (old_stderr < 0) {
     290                DEBUG(DEBUG_ERR, ("Failed to dup stderr for child logging\n"));
     291                close(old_stdout);
    287292                return -1;
    288293        }
  • vendor/current/ctdb/server/ctdb_recover.c

    r988 r989  
    314314}
    315315
     316struct db_pull_state {
     317        struct ctdb_context *ctdb;
     318        struct ctdb_db_context *ctdb_db;
     319        struct ctdb_marshall_buffer *recs;
     320        uint32_t pnn;
     321        uint64_t srvid;
     322        uint32_t num_records;
     323};
     324
     325static int traverse_db_pull(struct tdb_context *tdb, TDB_DATA key,
     326                            TDB_DATA data, void *private_data)
     327{
     328        struct db_pull_state *state = (struct db_pull_state *)private_data;
     329        struct ctdb_marshall_buffer *recs;
     330
     331        recs = ctdb_marshall_add(state->ctdb, state->recs,
     332                                 state->ctdb_db->db_id, 0, key, NULL, data);
     333        if (recs == NULL) {
     334                TALLOC_FREE(state->recs);
     335                return -1;
     336        }
     337        state->recs = recs;
     338
     339        if (talloc_get_size(state->recs) >=
     340                        state->ctdb->tunable.rec_buffer_size_limit) {
     341                TDB_DATA buffer;
     342                int ret;
     343
     344                buffer = ctdb_marshall_finish(state->recs);
     345                ret = ctdb_daemon_send_message(state->ctdb, state->pnn,
     346                                               state->srvid, buffer);
     347                if (ret != 0) {
     348                        TALLOC_FREE(state->recs);
     349                        return -1;
     350                }
     351
     352                state->num_records += state->recs->count;
     353                TALLOC_FREE(state->recs);
     354        }
     355
     356        return 0;
     357}
     358
     359int32_t ctdb_control_db_pull(struct ctdb_context *ctdb,
     360                             struct ctdb_req_control_old *c,
     361                             TDB_DATA indata, TDB_DATA *outdata)
     362{
     363        struct ctdb_pulldb_ext *pulldb_ext;
     364        struct ctdb_db_context *ctdb_db;
     365        struct db_pull_state state;
     366        int ret;
     367
     368        pulldb_ext = (struct ctdb_pulldb_ext *)indata.dptr;
     369
     370        ctdb_db = find_ctdb_db(ctdb, pulldb_ext->db_id);
     371        if (ctdb_db == NULL) {
     372                DEBUG(DEBUG_ERR,(__location__ " Unknown db 0x%08x\n",
     373                                 pulldb_ext->db_id));
     374                return -1;
     375        }
     376
     377        if (!ctdb_db_frozen(ctdb_db)) {
     378                DEBUG(DEBUG_ERR,
     379                      ("rejecting ctdb_control_pull_db when not frozen\n"));
     380                return -1;
     381        }
     382
     383        if (ctdb_db->unhealthy_reason) {
     384                /* this is just a warning, as the tdb should be empty anyway */
     385                DEBUG(DEBUG_WARNING,
     386                      ("db(%s) unhealty in ctdb_control_db_pull: %s\n",
     387                       ctdb_db->db_name, ctdb_db->unhealthy_reason));
     388        }
     389
     390        state.ctdb = ctdb;
     391        state.ctdb_db = ctdb_db;
     392        state.recs = NULL;
     393        state.pnn = c->hdr.srcnode;
     394        state.srvid = pulldb_ext->srvid;
     395        state.num_records = 0;
     396
     397        if (ctdb_lockdb_mark(ctdb_db) != 0) {
     398                DEBUG(DEBUG_ERR,
     399                      (__location__ " Failed to get lock on entire db - failing\n"));
     400                return -1;
     401        }
     402
     403        ret = tdb_traverse_read(ctdb_db->ltdb->tdb, traverse_db_pull, &state);
     404        if (ret == -1) {
     405                DEBUG(DEBUG_ERR,
     406                      (__location__ " Failed to get traverse db '%s'\n",
     407                       ctdb_db->db_name));
     408                ctdb_lockdb_unmark(ctdb_db);
     409                return -1;
     410        }
     411
     412        /* Last few records */
     413        if (state.recs != NULL) {
     414                TDB_DATA buffer;
     415
     416                buffer = ctdb_marshall_finish(state.recs);
     417                ret = ctdb_daemon_send_message(state.ctdb, state.pnn,
     418                                               state.srvid, buffer);
     419                if (ret != 0) {
     420                        TALLOC_FREE(state.recs);
     421                        ctdb_lockdb_unmark(ctdb_db);
     422                        return -1;
     423                }
     424
     425                state.num_records += state.recs->count;
     426                TALLOC_FREE(state.recs);
     427        }
     428
     429        ctdb_lockdb_unmark(ctdb_db);
     430
     431        outdata->dptr = talloc_size(outdata, sizeof(uint32_t));
     432        if (outdata->dptr == NULL) {
     433                DEBUG(DEBUG_ERR, (__location__ " Memory allocation error\n"));
     434                return -1;
     435        }
     436
     437        memcpy(outdata->dptr, (uint8_t *)&state.num_records, sizeof(uint32_t));
     438        outdata->dsize = sizeof(uint32_t);
     439
     440        return 0;
     441}
     442
    316443/*
    317444  push a bunch of records into a ltdb, filtering by rsn
     
    406533        ctdb_lockdb_unmark(ctdb_db);
    407534        return -1;
     535}
     536
     537struct db_push_state {
     538        struct ctdb_context *ctdb;
     539        struct ctdb_db_context *ctdb_db;
     540        uint64_t srvid;
     541        uint32_t num_records;
     542        bool failed;
     543};
     544
     545static void db_push_msg_handler(uint64_t srvid, TDB_DATA indata,
     546                                void *private_data)
     547{
     548        struct db_push_state *state = talloc_get_type(
     549                private_data, struct db_push_state);
     550        struct ctdb_marshall_buffer *recs;
     551        struct ctdb_rec_data_old *rec;
     552        int i, ret;
     553
     554        if (state->failed) {
     555                return;
     556        }
     557
     558        recs = (struct ctdb_marshall_buffer *)indata.dptr;
     559        rec = (struct ctdb_rec_data_old *)&recs->data[0];
     560
     561        DEBUG(DEBUG_INFO, ("starting push of %u records for dbid 0x%x\n",
     562                           recs->count, recs->db_id));
     563
     564        for (i=0; i<recs->count; i++) {
     565                TDB_DATA key, data;
     566                struct ctdb_ltdb_header *hdr;
     567
     568                key.dptr = &rec->data[0];
     569                key.dsize = rec->keylen;
     570                data.dptr = &rec->data[key.dsize];
     571                data.dsize = rec->datalen;
     572
     573                if (data.dsize < sizeof(struct ctdb_ltdb_header)) {
     574                        DEBUG(DEBUG_CRIT,(__location__ " bad ltdb record\n"));
     575                        goto failed;
     576                }
     577
     578                hdr = (struct ctdb_ltdb_header *)data.dptr;
     579                /* Strip off any read only record flags.
     580                 * All readonly records are revoked implicitely by a recovery.
     581                 */
     582                hdr->flags &= ~CTDB_REC_RO_FLAGS;
     583
     584                data.dptr += sizeof(*hdr);
     585                data.dsize -= sizeof(*hdr);
     586
     587                ret = ctdb_ltdb_store(state->ctdb_db, key, hdr, data);
     588                if (ret != 0) {
     589                        DEBUG(DEBUG_ERR,
     590                              (__location__ " Unable to store record\n"));
     591                        goto failed;
     592                }
     593
     594                rec = (struct ctdb_rec_data_old *)(rec->length + (uint8_t *)rec);
     595        }
     596
     597        DEBUG(DEBUG_DEBUG, ("finished push of %u records for dbid 0x%x\n",
     598                            recs->count, recs->db_id));
     599
     600        state->num_records += recs->count;
     601        return;
     602
     603failed:
     604        state->failed = true;
     605}
     606
     607int32_t ctdb_control_db_push_start(struct ctdb_context *ctdb, TDB_DATA indata)
     608{
     609        struct ctdb_pulldb_ext *pulldb_ext;
     610        struct ctdb_db_context *ctdb_db;
     611        struct db_push_state *state;
     612        int ret;
     613
     614        pulldb_ext = (struct ctdb_pulldb_ext *)indata.dptr;
     615
     616        ctdb_db = find_ctdb_db(ctdb, pulldb_ext->db_id);
     617        if (ctdb_db == NULL) {
     618                DEBUG(DEBUG_ERR,
     619                      (__location__ " Unknown db 0x%08x\n", pulldb_ext->db_id));
     620                return -1;
     621        }
     622
     623        if (!ctdb_db_frozen(ctdb_db)) {
     624                DEBUG(DEBUG_ERR,
     625                      ("rejecting ctdb_control_db_push_start when not frozen\n"));
     626                return -1;
     627        }
     628
     629        if (ctdb_db->push_started) {
     630                DEBUG(DEBUG_WARNING,
     631                      (__location__ " DB push already started for %s\n",
     632                       ctdb_db->db_name));
     633
     634                /* De-register old state */
     635                state = (struct db_push_state *)ctdb_db->push_state;
     636                if (state != NULL) {
     637                        srvid_deregister(ctdb->srv, state->srvid, state);
     638                        talloc_free(state);
     639                        ctdb_db->push_state = NULL;
     640                }
     641        }
     642
     643        state = talloc_zero(ctdb_db, struct db_push_state);
     644        if (state == NULL) {
     645                DEBUG(DEBUG_ERR, (__location__ " Memory allocation error\n"));
     646                return -1;
     647        }
     648
     649        state->ctdb = ctdb;
     650        state->ctdb_db = ctdb_db;
     651        state->srvid = pulldb_ext->srvid;
     652        state->failed = false;
     653
     654        ret = srvid_register(ctdb->srv, state, state->srvid,
     655                             db_push_msg_handler, state);
     656        if (ret != 0) {
     657                DEBUG(DEBUG_ERR,
     658                      (__location__ " Failed to register srvid for db push\n"));
     659                talloc_free(state);
     660                return -1;
     661        }
     662
     663        if (ctdb_lockdb_mark(ctdb_db) != 0) {
     664                DEBUG(DEBUG_ERR,
     665                      (__location__ " Failed to get lock on entire db - failing\n"));
     666                srvid_deregister(ctdb->srv, state->srvid, state);
     667                talloc_free(state);
     668                return -1;
     669        }
     670
     671        ctdb_db->push_started = true;
     672        ctdb_db->push_state = state;
     673
     674        return 0;
     675}
     676
     677int32_t ctdb_control_db_push_confirm(struct ctdb_context *ctdb,
     678                                     TDB_DATA indata, TDB_DATA *outdata)
     679{
     680        uint32_t db_id;
     681        struct ctdb_db_context *ctdb_db;
     682        struct db_push_state *state;
     683
     684        db_id = *(uint32_t *)indata.dptr;
     685
     686        ctdb_db = find_ctdb_db(ctdb, db_id);
     687        if (ctdb_db == NULL) {
     688                DEBUG(DEBUG_ERR,(__location__ " Unknown db 0x%08x\n", db_id));
     689                return -1;
     690        }
     691
     692        if (!ctdb_db_frozen(ctdb_db)) {
     693                DEBUG(DEBUG_ERR,
     694                      ("rejecting ctdb_control_db_push_confirm when not frozen\n"));
     695                return -1;
     696        }
     697
     698        if (!ctdb_db->push_started) {
     699                DEBUG(DEBUG_ERR, (__location__ " DB push not started\n"));
     700                return -1;
     701        }
     702
     703        if (ctdb_db->readonly) {
     704                DEBUG(DEBUG_ERR,
     705                      ("Clearing the tracking database for dbid 0x%x\n",
     706                       ctdb_db->db_id));
     707                if (tdb_wipe_all(ctdb_db->rottdb) != 0) {
     708                        DEBUG(DEBUG_ERR,
     709                              ("Failed to wipe tracking database for 0x%x."
     710                               " Dropping read-only delegation support\n",
     711                               ctdb_db->db_id));
     712                        ctdb_db->readonly = false;
     713                        tdb_close(ctdb_db->rottdb);
     714                        ctdb_db->rottdb = NULL;
     715                        ctdb_db->readonly = false;
     716                }
     717
     718                while (ctdb_db->revokechild_active != NULL) {
     719                        talloc_free(ctdb_db->revokechild_active);
     720                }
     721        }
     722
     723        ctdb_lockdb_unmark(ctdb_db);
     724
     725        state = (struct db_push_state *)ctdb_db->push_state;
     726        if (state == NULL) {
     727                DEBUG(DEBUG_ERR, (__location__ " Missing push db state\n"));
     728                return -1;
     729        }
     730
     731        srvid_deregister(ctdb->srv, state->srvid, state);
     732
     733        outdata->dptr = talloc_size(outdata, sizeof(uint32_t));
     734        if (outdata->dptr == NULL) {
     735                DEBUG(DEBUG_ERR, (__location__ " Memory allocation error\n"));
     736                talloc_free(state);
     737                ctdb_db->push_state = NULL;
     738                return -1;
     739        }
     740
     741        memcpy(outdata->dptr, (uint8_t *)&state->num_records, sizeof(uint32_t));
     742        outdata->dsize = sizeof(uint32_t);
     743
     744        talloc_free(state);
     745        ctdb_db->push_started = false;
     746        ctdb_db->push_state = NULL;
     747
     748        return 0;
    408749}
    409750
     
    10331374                if (data.dsize < sizeof(struct ctdb_ltdb_header)) {
    10341375                        DEBUG(DEBUG_CRIT,(__location__ " bad ltdb record in indata\n"));
     1376                        talloc_free(records);
    10351377                        return -1;
    10361378                }
     
    12251567                        DEBUG(DEBUG_CRIT, (__location__ " bad ltdb record "
    12261568                                           "in indata\n"));
     1569                        talloc_free(records);
    12271570                        return -1;
    12281571                }
  • vendor/current/ctdb/server/ctdb_recoverd.c

    r988 r989  
    253253        uint32_t *force_rebalance_nodes;
    254254        struct ctdb_node_capabilities *caps;
     255        bool frozen_on_inactive;
    255256};
    256257
     
    17821783        }
    17831784
     1785        setenv("CTDB_DBDIR_STATE", rec->ctdb->db_directory_state, 1);
     1786
    17841787        if (!ctdb_vfork_with_logging(state, rec->ctdb, "recovery", prog, nargs,
    17851788                                     args, NULL, NULL, &state->pid)) {
     
    19811984
    19821985        DEBUG(DEBUG_NOTICE, (__location__ " Recovery - disabled recovery mode\n"));
     1986
     1987        /* execute the "recovered" event script on all nodes */
     1988        ret = run_recovered_eventscript(rec, nodemap, "do_recovery");
     1989        if (ret!=0) {
     1990                DEBUG(DEBUG_ERR, (__location__ " Unable to run the 'recovered' event on cluster. Recovery process failed.\n"));
     1991                return -1;
     1992        }
     1993
     1994        DEBUG(DEBUG_NOTICE, (__location__ " Recovery - finished the recovered event\n"));
    19831995
    19841996        return 0;
     
    21572169        do_takeover_run(rec, nodemap, false);
    21582170
    2159         /* execute the "recovered" event script on all nodes */
    2160         ret = run_recovered_eventscript(rec, nodemap, "do_recovery");
    2161         if (ret!=0) {
    2162                 DEBUG(DEBUG_ERR, (__location__ " Unable to run the 'recovered' event on cluster. Recovery process failed.\n"));
    2163                 goto fail;
    2164         }
    2165 
    2166         DEBUG(DEBUG_NOTICE, (__location__ " Recovery - finished the recovered event\n"));
    2167 
    21682171        /* send a message to all clients telling them that the cluster
    21692172           has been reconfigured */
     
    26592662}
    26602663
     2664/*
     2665 * handler for assigning banning credits
     2666 */
     2667static void banning_handler(uint64_t srvid, TDB_DATA data, void *private_data)
     2668{
     2669        struct ctdb_recoverd *rec = talloc_get_type(
     2670                private_data, struct ctdb_recoverd);
     2671        uint32_t ban_pnn;
     2672
     2673        /* Ignore if we are not recmaster */
     2674        if (rec->ctdb->pnn != rec->recmaster) {
     2675                return;
     2676        }
     2677
     2678        if (data.dsize != sizeof(uint32_t)) {
     2679                DEBUG(DEBUG_ERR, (__location__ "invalid data size %zu\n",
     2680                                  data.dsize));
     2681                return;
     2682        }
     2683
     2684        ban_pnn = *(uint32_t *)data.dptr;
     2685
     2686        ctdb_set_culprit_count(rec, ban_pnn, rec->nodemap->num);
     2687}
    26612688
    26622689/*
     
    34903517                                return;
    34913518                        }
    3492                         ret = ctdb_ctrl_freeze(ctdb, CONTROL_TIMEOUT(), CTDB_CURRENT_NODE);
     3519                }
     3520                if (! rec->frozen_on_inactive) {
     3521                        ret = ctdb_ctrl_freeze(ctdb, CONTROL_TIMEOUT(),
     3522                                               CTDB_CURRENT_NODE);
    34933523                        if (ret != 0) {
    3494                                 DEBUG(DEBUG_ERR,(__location__ " Failed to freeze node in STOPPED or BANNED state\n"));
     3524                                DEBUG(DEBUG_ERR,
     3525                                      (__location__ " Failed to freeze node "
     3526                                       "in STOPPED or BANNED state\n"));
    34953527                                return;
    34963528                        }
     3529
     3530                        rec->frozen_on_inactive = true;
    34973531                }
    34983532
     
    35033537                return;
    35043538        }
     3539
     3540        rec->frozen_on_inactive = false;
    35053541
    35063542        /* If we are not the recmaster then do some housekeeping */
     
    38833919
    38843920        rec->priority_time = timeval_current();
     3921        rec->frozen_on_inactive = false;
    38853922
    38863923        /* register a message port for sending memory dumps */
    38873924        ctdb_client_set_message_handler(ctdb, CTDB_SRVID_MEM_DUMP, mem_dump_handler, rec);
     3925
     3926        /* when a node is assigned banning credits */
     3927        ctdb_client_set_message_handler(ctdb, CTDB_SRVID_BANNING,
     3928                                        banning_handler, rec);
    38883929
    38893930        /* register a message port for recovery elections */
  • vendor/current/ctdb/server/ctdb_recovery_helper.c

    r988 r989  
    3535#include "client/client.h"
    3636
    37 #define TIMEOUT()       timeval_current_ofs(10, 0)
     37static int recover_timeout = 30;
     38
     39#define NUM_RETRIES     3
     40
     41#define TIMEOUT()       timeval_current_ofs(recover_timeout, 0)
    3842
    3943static void LOG(const char *fmt, ...)
     
    6468}
    6569
     70static bool generic_recv(struct tevent_req *req, int *perr)
     71{
     72        int err;
     73
     74        if (tevent_req_is_unix_error(req, &err)) {
     75                if (perr != NULL) {
     76                        *perr = err;
     77                }
     78                return false;
     79        }
     80
     81        return true;
     82}
     83
     84static uint64_t rec_srvid = CTDB_SRVID_RECOVERY;
     85
     86static uint64_t srvid_next(void)
     87{
     88        rec_srvid += 1;
     89        return rec_srvid;
     90}
     91
    6692/*
    6793 * Recovery database functions
     
    81107                                          uint32_t hash_size, bool persistent)
    82108{
     109        static char *db_dir_state = NULL;
    83110        struct recdb_context *recdb;
    84111        unsigned int tdb_flags;
     
    89116        }
    90117
     118        if (db_dir_state == NULL) {
     119                db_dir_state = getenv("CTDB_DBDIR_STATE");
     120        }
     121
    91122        recdb->db_name = db_name;
    92123        recdb->db_id = db_id;
    93124        recdb->db_path = talloc_asprintf(recdb, "%s/recdb.%s",
    94                                          dirname(discard_const(db_path)),
     125                                         db_dir_state != NULL ?
     126                                            db_dir_state :
     127                                            dirname(discard_const(db_path)),
    95128                                         db_name);
    96129        if (recdb->db_path == NULL) {
     
    113146}
    114147
     148static uint32_t recdb_id(struct recdb_context *recdb)
     149{
     150        return recdb->db_id;
     151}
     152
    115153static const char *recdb_name(struct recdb_context *recdb)
    116154{
    117155        return recdb->db_name;
     156}
     157
     158static const char *recdb_path(struct recdb_context *recdb)
     159{
     160        return recdb->db_path;
     161}
     162
     163static struct tdb_context *recdb_tdb(struct recdb_context *recdb)
     164{
     165        return recdb->db->tdb;
     166}
     167
     168static bool recdb_persistent(struct recdb_context *recdb)
     169{
     170        return recdb->persistent;
    118171}
    119172
     
    141194
    142195        /* fetch the existing record, if any */
    143         prev_data = tdb_fetch(state->recdb->db->tdb, key);
     196        prev_data = tdb_fetch(recdb_tdb(state->recdb), key);
    144197
    145198        if (prev_data.dptr != NULL) {
     
    155208        }
    156209
    157         ret = tdb_store(state->recdb->db->tdb, key, data, TDB_REPLACE);
     210        ret = tdb_store(recdb_tdb(state->recdb), key, data, TDB_REPLACE);
    158211        if (ret != 0) {
    159212                return -1;
     
    179232}
    180233
    181 struct recdb_traverse_state {
    182         struct ctdb_rec_buffer *recbuf;
    183         uint32_t pnn;
    184         uint32_t reqid;
    185         bool persistent;
    186         bool failed;
    187 };
    188 
    189 static int recdb_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
    190                           void *private_data)
    191 {
    192         struct recdb_traverse_state *state =
    193                 (struct recdb_traverse_state *)private_data;
     234/* This function decides which records from recdb are retained */
     235static int recbuf_filter_add(struct ctdb_rec_buffer *recbuf, bool persistent,
     236                             uint32_t reqid, uint32_t dmaster,
     237                             TDB_DATA key, TDB_DATA data)
     238{
    194239        struct ctdb_ltdb_header *header;
    195240        int ret;
     
    225270         * data structures built from the various tdb-level records.
    226271         */
    227         if (!state->persistent &&
    228             data.dsize <= sizeof(struct ctdb_ltdb_header)) {
     272        if (!persistent && data.dsize <= sizeof(struct ctdb_ltdb_header)) {
    229273                return 0;
    230274        }
     
    232276        /* update the dmaster field to point to us */
    233277        header = (struct ctdb_ltdb_header *)data.dptr;
    234         if (!state->persistent) {
    235                 header->dmaster = state->pnn;
     278        if (!persistent) {
     279                header->dmaster = dmaster;
    236280                header->flags |= CTDB_REC_FLAG_MIGRATED_WITH_DATA;
    237281        }
    238282
    239         ret = ctdb_rec_buffer_add(state->recbuf, state->recbuf, state->reqid,
    240                                   NULL, key, data);
     283        ret = ctdb_rec_buffer_add(recbuf, recbuf, reqid, NULL, key, data);
     284        if (ret != 0) {
     285                return ret;
     286        }
     287
     288        return 0;
     289}
     290
     291struct recdb_records_traverse_state {
     292        struct ctdb_rec_buffer *recbuf;
     293        uint32_t dmaster;
     294        uint32_t reqid;
     295        bool persistent;
     296        bool failed;
     297};
     298
     299static int recdb_records_traverse(struct tdb_context *tdb,
     300                                  TDB_DATA key, TDB_DATA data,
     301                                  void *private_data)
     302{
     303        struct recdb_records_traverse_state *state =
     304                (struct recdb_records_traverse_state *)private_data;
     305        int ret;
     306
     307        ret = recbuf_filter_add(state->recbuf, state->persistent,
     308                                state->reqid, state->dmaster, key, data);
    241309        if (ret != 0) {
    242310                state->failed = true;
     
    248316
    249317static struct ctdb_rec_buffer *recdb_records(struct recdb_context *recdb,
    250                                              TALLOC_CTX *mem_ctx, uint32_t pnn)
    251 {
    252         struct recdb_traverse_state state;
    253         int ret;
    254 
    255         state.recbuf = ctdb_rec_buffer_init(mem_ctx, recdb->db_id);
     318                                             TALLOC_CTX *mem_ctx,
     319                                             uint32_t dmaster)
     320{
     321        struct recdb_records_traverse_state state;
     322        int ret;
     323
     324        state.recbuf = ctdb_rec_buffer_init(mem_ctx, recdb_id(recdb));
    256325        if (state.recbuf == NULL) {
    257326                return NULL;
    258327        }
    259         state.pnn = pnn;
     328        state.dmaster = dmaster;
    260329        state.reqid = 0;
    261         state.persistent = recdb->persistent;
     330        state.persistent = recdb_persistent(recdb);
    262331        state.failed = false;
    263332
    264         ret = tdb_traverse_read(recdb->db->tdb, recdb_traverse, &state);
     333        ret = tdb_traverse_read(recdb_tdb(recdb), recdb_records_traverse,
     334                                &state);
     335        if (ret == -1 || state.failed) {
     336                LOG("Failed to marshall recovery records for %s\n",
     337                    recdb_name(recdb));
     338                TALLOC_FREE(state.recbuf);
     339                return NULL;
     340        }
     341
     342        return state.recbuf;
     343}
     344
     345struct recdb_file_traverse_state {
     346        struct ctdb_rec_buffer *recbuf;
     347        struct recdb_context *recdb;
     348        TALLOC_CTX *mem_ctx;
     349        uint32_t dmaster;
     350        uint32_t reqid;
     351        bool persistent;
     352        bool failed;
     353        int fd;
     354        int max_size;
     355        int num_buffers;
     356};
     357
     358static int recdb_file_traverse(struct tdb_context *tdb,
     359                               TDB_DATA key, TDB_DATA data,
     360                               void *private_data)
     361{
     362        struct recdb_file_traverse_state *state =
     363                (struct recdb_file_traverse_state *)private_data;
     364        int ret;
     365
     366        ret = recbuf_filter_add(state->recbuf, state->persistent,
     367                                state->reqid, state->dmaster, key, data);
     368        if (ret != 0) {
     369                state->failed = true;
     370                return ret;
     371        }
     372
     373        if (ctdb_rec_buffer_len(state->recbuf) > state->max_size) {
     374                ret = ctdb_rec_buffer_write(state->recbuf, state->fd);
     375                if (ret != 0) {
     376                        LOG("Failed to collect recovery records for %s\n",
     377                            recdb_name(state->recdb));
     378                        state->failed = true;
     379                        return ret;
     380                }
     381
     382                state->num_buffers += 1;
     383
     384                TALLOC_FREE(state->recbuf);
     385                state->recbuf = ctdb_rec_buffer_init(state->mem_ctx,
     386                                                     recdb_id(state->recdb));
     387                if (state->recbuf == NULL) {
     388                        state->failed = true;
     389                        return ENOMEM;
     390                }
     391        }
     392
     393        return 0;
     394}
     395
     396static int recdb_file(struct recdb_context *recdb, TALLOC_CTX *mem_ctx,
     397                      uint32_t dmaster, int fd, int max_size)
     398{
     399        struct recdb_file_traverse_state state;
     400        int ret;
     401
     402        state.recbuf = ctdb_rec_buffer_init(mem_ctx, recdb_id(recdb));
     403        if (state.recbuf == NULL) {
     404                return -1;
     405        }
     406        state.recdb = recdb;
     407        state.mem_ctx = mem_ctx;
     408        state.dmaster = dmaster;
     409        state.reqid = 0;
     410        state.persistent = recdb_persistent(recdb);
     411        state.failed = false;
     412        state.fd = fd;
     413        state.max_size = max_size;
     414        state.num_buffers = 0;
     415
     416        ret = tdb_traverse_read(recdb_tdb(recdb), recdb_file_traverse, &state);
    265417        if (ret == -1 || state.failed) {
    266418                TALLOC_FREE(state.recbuf);
     419                return -1;
     420        }
     421
     422        ret = ctdb_rec_buffer_write(state.recbuf, fd);
     423        if (ret != 0) {
     424                LOG("Failed to collect recovery records for %s\n",
     425                    recdb_name(recdb));
     426                TALLOC_FREE(state.recbuf);
     427                return -1;
     428        }
     429        state.num_buffers += 1;
     430
     431        LOG("Wrote %d buffers of recovery records for %s\n",
     432            state.num_buffers, recdb_name(recdb));
     433
     434        return state.num_buffers;
     435}
     436
     437/*
     438 * Pull database from a single node
     439 */
     440
     441struct pull_database_state {
     442        struct tevent_context *ev;
     443        struct ctdb_client_context *client;
     444        struct recdb_context *recdb;
     445        uint32_t pnn;
     446        uint64_t srvid;
     447        int num_records;
     448};
     449
     450static void pull_database_handler(uint64_t srvid, TDB_DATA data,
     451                                  void *private_data);
     452static void pull_database_register_done(struct tevent_req *subreq);
     453static void pull_database_old_done(struct tevent_req *subreq);
     454static void pull_database_unregister_done(struct tevent_req *subreq);
     455static void pull_database_new_done(struct tevent_req *subreq);
     456
     457static struct tevent_req *pull_database_send(
     458                        TALLOC_CTX *mem_ctx,
     459                        struct tevent_context *ev,
     460                        struct ctdb_client_context *client,
     461                        uint32_t pnn, uint32_t caps,
     462                        struct recdb_context *recdb)
     463{
     464        struct tevent_req *req, *subreq;
     465        struct pull_database_state *state;
     466        struct ctdb_req_control request;
     467
     468        req = tevent_req_create(mem_ctx, &state, struct pull_database_state);
     469        if (req == NULL) {
    267470                return NULL;
    268471        }
    269472
    270         return state.recbuf;
     473        state->ev = ev;
     474        state->client = client;
     475        state->recdb = recdb;
     476        state->pnn = pnn;
     477        state->srvid = srvid_next();
     478
     479        if (caps & CTDB_CAP_FRAGMENTED_CONTROLS) {
     480                subreq = ctdb_client_set_message_handler_send(
     481                                        state, state->ev, state->client,
     482                                        state->srvid, pull_database_handler,
     483                                        req);
     484                if (tevent_req_nomem(subreq, req)) {
     485                        return tevent_req_post(req, ev);
     486                }
     487
     488                tevent_req_set_callback(subreq, pull_database_register_done,
     489                                        req);
     490
     491        } else {
     492                struct ctdb_pulldb pulldb;
     493
     494                pulldb.db_id = recdb_id(recdb);
     495                pulldb.lmaster = CTDB_LMASTER_ANY;
     496
     497                ctdb_req_control_pull_db(&request, &pulldb);
     498                subreq = ctdb_client_control_send(state, state->ev,
     499                                                  state->client,
     500                                                  pnn, TIMEOUT(),
     501                                                  &request);
     502                if (tevent_req_nomem(subreq, req)) {
     503                        return tevent_req_post(req, ev);
     504                }
     505                tevent_req_set_callback(subreq, pull_database_old_done, req);
     506        }
     507
     508        return req;
     509}
     510
     511static void pull_database_handler(uint64_t srvid, TDB_DATA data,
     512                                  void *private_data)
     513{
     514        struct tevent_req *req = talloc_get_type_abort(
     515                private_data, struct tevent_req);
     516        struct pull_database_state *state = tevent_req_data(
     517                req, struct pull_database_state);
     518        struct ctdb_rec_buffer *recbuf;
     519        int ret;
     520        bool status;
     521
     522        if (srvid != state->srvid) {
     523                return;
     524        }
     525
     526        ret = ctdb_rec_buffer_pull(data.dptr, data.dsize, state, &recbuf);
     527        if (ret != 0) {
     528                LOG("Invalid data received for DB_PULL messages\n");
     529                return;
     530        }
     531
     532        if (recbuf->db_id != recdb_id(state->recdb)) {
     533                talloc_free(recbuf);
     534                LOG("Invalid dbid:%08x for DB_PULL messages for %s\n",
     535                    recbuf->db_id, recdb_name(state->recdb));
     536                return;
     537        }
     538
     539        status = recdb_add(state->recdb, ctdb_client_pnn(state->client),
     540                           recbuf);
     541        if (! status) {
     542                talloc_free(recbuf);
     543                LOG("Failed to add records to recdb for %s\n",
     544                    recdb_name(state->recdb));
     545                return;
     546        }
     547
     548        state->num_records += recbuf->count;
     549        talloc_free(recbuf);
     550}
     551
     552static void pull_database_register_done(struct tevent_req *subreq)
     553{
     554        struct tevent_req *req = tevent_req_callback_data(
     555                subreq, struct tevent_req);
     556        struct pull_database_state *state = tevent_req_data(
     557                req, struct pull_database_state);
     558        struct ctdb_req_control request;
     559        struct ctdb_pulldb_ext pulldb_ext;
     560        int ret;
     561        bool status;
     562
     563        status = ctdb_client_set_message_handler_recv(subreq, &ret);
     564        TALLOC_FREE(subreq);
     565        if (! status) {
     566                LOG("failed to set message handler for DB_PULL for %s\n",
     567                    recdb_name(state->recdb));
     568                tevent_req_error(req, ret);
     569                return;
     570        }
     571
     572        pulldb_ext.db_id = recdb_id(state->recdb);
     573        pulldb_ext.lmaster = CTDB_LMASTER_ANY;
     574        pulldb_ext.srvid = state->srvid;
     575
     576        ctdb_req_control_db_pull(&request, &pulldb_ext);
     577        subreq = ctdb_client_control_send(state, state->ev, state->client,
     578                                          state->pnn, TIMEOUT(), &request);
     579        if (tevent_req_nomem(subreq, req)) {
     580                return;
     581        }
     582        tevent_req_set_callback(subreq, pull_database_new_done, req);
     583}
     584
     585static void pull_database_old_done(struct tevent_req *subreq)
     586{
     587        struct tevent_req *req = tevent_req_callback_data(
     588                subreq, struct tevent_req);
     589        struct pull_database_state *state = tevent_req_data(
     590                req, struct pull_database_state);
     591        struct ctdb_reply_control *reply;
     592        struct ctdb_rec_buffer *recbuf;
     593        int ret;
     594        bool status;
     595
     596        status = ctdb_client_control_recv(subreq, &ret, state, &reply);
     597        TALLOC_FREE(subreq);
     598        if (! status) {
     599                LOG("control PULL_DB failed for %s on node %u, ret=%d\n",
     600                    recdb_name(state->recdb), state->pnn, ret);
     601                tevent_req_error(req, ret);
     602                return;
     603        }
     604
     605        ret = ctdb_reply_control_pull_db(reply, state, &recbuf);
     606        talloc_free(reply);
     607        if (ret != 0) {
     608                tevent_req_error(req, ret);
     609                return;
     610        }
     611
     612        status = recdb_add(state->recdb, ctdb_client_pnn(state->client),
     613                           recbuf);
     614        if (! status) {
     615                talloc_free(recbuf);
     616                tevent_req_error(req, EIO);
     617                return;
     618        }
     619
     620        state->num_records = recbuf->count;
     621        talloc_free(recbuf);
     622
     623        LOG("Pulled %d records for db %s from node %d\n",
     624            state->num_records, recdb_name(state->recdb), state->pnn);
     625
     626        tevent_req_done(req);
     627}
     628
     629static void pull_database_new_done(struct tevent_req *subreq)
     630{
     631        struct tevent_req *req = tevent_req_callback_data(
     632                subreq, struct tevent_req);
     633        struct pull_database_state *state = tevent_req_data(
     634                req, struct pull_database_state);
     635        struct ctdb_reply_control *reply;
     636        uint32_t num_records;
     637        int ret;
     638        bool status;
     639
     640        status = ctdb_client_control_recv(subreq, &ret, state, &reply);
     641        TALLOC_FREE(subreq);
     642        if (! status) {
     643                LOG("control DB_PULL failed for %s on node %u, ret=%d\n",
     644                    recdb_name(state->recdb), state->pnn, ret);
     645                tevent_req_error(req, ret);
     646                return;
     647        }
     648
     649        ret = ctdb_reply_control_db_pull(reply, &num_records);
     650        talloc_free(reply);
     651        if (num_records != state->num_records) {
     652                LOG("mismatch (%u != %u) in DB_PULL records for %s\n",
     653                    num_records, state->num_records, recdb_name(state->recdb));
     654                tevent_req_error(req, EIO);
     655                return;
     656        }
     657
     658        LOG("Pulled %d records for db %s from node %d\n",
     659            state->num_records, recdb_name(state->recdb), state->pnn);
     660
     661        subreq = ctdb_client_remove_message_handler_send(
     662                                        state, state->ev, state->client,
     663                                        state->srvid, req);
     664        if (tevent_req_nomem(subreq, req)) {
     665                return;
     666        }
     667        tevent_req_set_callback(subreq, pull_database_unregister_done, req);
     668}
     669
     670static void pull_database_unregister_done(struct tevent_req *subreq)
     671{
     672        struct tevent_req *req = tevent_req_callback_data(
     673                subreq, struct tevent_req);
     674        struct pull_database_state *state = tevent_req_data(
     675                req, struct pull_database_state);
     676        int ret;
     677        bool status;
     678
     679        status = ctdb_client_remove_message_handler_recv(subreq, &ret);
     680        TALLOC_FREE(subreq);
     681        if (! status) {
     682                LOG("failed to remove message handler for DB_PULL for %s\n",
     683                    recdb_name(state->recdb));
     684                tevent_req_error(req, ret);
     685                return;
     686        }
     687
     688        tevent_req_done(req);
     689}
     690
     691static bool pull_database_recv(struct tevent_req *req, int *perr)
     692{
     693        return generic_recv(req, perr);
     694}
     695
     696/*
     697 * Push database to specified nodes (old style)
     698 */
     699
     700struct push_database_old_state {
     701        struct tevent_context *ev;
     702        struct ctdb_client_context *client;
     703        struct recdb_context *recdb;
     704        uint32_t *pnn_list;
     705        int count;
     706        struct ctdb_rec_buffer *recbuf;
     707        int index;
     708};
     709
     710static void push_database_old_push_done(struct tevent_req *subreq);
     711
     712static struct tevent_req *push_database_old_send(
     713                        TALLOC_CTX *mem_ctx,
     714                        struct tevent_context *ev,
     715                        struct ctdb_client_context *client,
     716                        uint32_t *pnn_list, int count,
     717                        struct recdb_context *recdb)
     718{
     719        struct tevent_req *req, *subreq;
     720        struct push_database_old_state *state;
     721        struct ctdb_req_control request;
     722        uint32_t pnn;
     723
     724        req = tevent_req_create(mem_ctx, &state,
     725                                struct push_database_old_state);
     726        if (req == NULL) {
     727                return NULL;
     728        }
     729
     730        state->ev = ev;
     731        state->client = client;
     732        state->recdb = recdb;
     733        state->pnn_list = pnn_list;
     734        state->count = count;
     735        state->index = 0;
     736
     737        state->recbuf = recdb_records(recdb, state,
     738                                      ctdb_client_pnn(client));
     739        if (tevent_req_nomem(state->recbuf, req)) {
     740                return tevent_req_post(req, ev);
     741        }
     742
     743        pnn = state->pnn_list[state->index];
     744
     745        ctdb_req_control_push_db(&request, state->recbuf);
     746        subreq = ctdb_client_control_send(state, ev, client, pnn,
     747                                          TIMEOUT(), &request);
     748        if (tevent_req_nomem(subreq, req)) {
     749                return tevent_req_post(req, ev);
     750        }
     751        tevent_req_set_callback(subreq, push_database_old_push_done, req);
     752
     753        return req;
     754}
     755
     756static void push_database_old_push_done(struct tevent_req *subreq)
     757{
     758        struct tevent_req *req = tevent_req_callback_data(
     759                subreq, struct tevent_req);
     760        struct push_database_old_state *state = tevent_req_data(
     761                req, struct push_database_old_state);
     762        struct ctdb_req_control request;
     763        uint32_t pnn;
     764        int ret;
     765        bool status;
     766
     767        status = ctdb_client_control_recv(subreq, &ret, NULL, NULL);
     768        TALLOC_FREE(subreq);
     769        if (! status) {
     770                LOG("control PUSH_DB failed for db %s on node %u, ret=%d\n",
     771                    recdb_name(state->recdb), state->pnn_list[state->index],
     772                    ret);
     773                tevent_req_error(req, ret);
     774                return;
     775        }
     776
     777        state->index += 1;
     778        if (state->index == state->count) {
     779                TALLOC_FREE(state->recbuf);
     780                tevent_req_done(req);
     781                return;
     782        }
     783
     784        pnn = state->pnn_list[state->index];
     785
     786        ctdb_req_control_push_db(&request, state->recbuf);
     787        subreq = ctdb_client_control_send(state, state->ev, state->client,
     788                                          pnn, TIMEOUT(), &request);
     789        if (tevent_req_nomem(subreq, req)) {
     790                return;
     791        }
     792        tevent_req_set_callback(subreq, push_database_old_push_done, req);
     793}
     794
     795static bool push_database_old_recv(struct tevent_req *req, int *perr)
     796{
     797        return generic_recv(req, perr);
     798}
     799
     800/*
     801 * Push database to specified nodes (new style)
     802 */
     803
     804struct push_database_new_state {
     805        struct tevent_context *ev;
     806        struct ctdb_client_context *client;
     807        struct recdb_context *recdb;
     808        uint32_t *pnn_list;
     809        int count;
     810        uint64_t srvid;
     811        uint32_t dmaster;
     812        int fd;
     813        int num_buffers;
     814        int num_buffers_sent;
     815        int num_records;
     816};
     817
     818static void push_database_new_started(struct tevent_req *subreq);
     819static void push_database_new_send_msg(struct tevent_req *req);
     820static void push_database_new_send_done(struct tevent_req *subreq);
     821static void push_database_new_confirmed(struct tevent_req *subreq);
     822
     823static struct tevent_req *push_database_new_send(
     824                        TALLOC_CTX *mem_ctx,
     825                        struct tevent_context *ev,
     826                        struct ctdb_client_context *client,
     827                        uint32_t *pnn_list, int count,
     828                        struct recdb_context *recdb,
     829                        int max_size)
     830{
     831        struct tevent_req *req, *subreq;
     832        struct push_database_new_state *state;
     833        struct ctdb_req_control request;
     834        struct ctdb_pulldb_ext pulldb_ext;
     835        char *filename;
     836        off_t offset;
     837
     838        req = tevent_req_create(mem_ctx, &state,
     839                                struct push_database_new_state);
     840        if (req == NULL) {
     841                return NULL;
     842        }
     843
     844        state->ev = ev;
     845        state->client = client;
     846        state->recdb = recdb;
     847        state->pnn_list = pnn_list;
     848        state->count = count;
     849
     850        state->srvid = srvid_next();
     851        state->dmaster = ctdb_client_pnn(client);
     852        state->num_buffers_sent = 0;
     853        state->num_records = 0;
     854
     855        filename = talloc_asprintf(state, "%s.dat", recdb_path(recdb));
     856        if (tevent_req_nomem(filename, req)) {
     857                return tevent_req_post(req, ev);
     858        }
     859
     860        state->fd = open(filename, O_RDWR|O_CREAT, 0644);
     861        if (state->fd == -1) {
     862                tevent_req_error(req, errno);
     863                return tevent_req_post(req, ev);
     864        }
     865        unlink(filename);
     866        talloc_free(filename);
     867
     868        state->num_buffers = recdb_file(recdb, state, state->dmaster,
     869                                        state->fd, max_size);
     870        if (state->num_buffers == -1) {
     871                tevent_req_error(req, ENOMEM);
     872                return tevent_req_post(req, ev);
     873        }
     874
     875        offset = lseek(state->fd, 0, SEEK_SET);
     876        if (offset != 0) {
     877                tevent_req_error(req, EIO);
     878                return tevent_req_post(req, ev);
     879        }
     880
     881        pulldb_ext.db_id = recdb_id(recdb);
     882        pulldb_ext.srvid = state->srvid;
     883
     884        ctdb_req_control_db_push_start(&request, &pulldb_ext);
     885        subreq = ctdb_client_control_multi_send(state, ev, client,
     886                                                pnn_list, count,
     887                                                TIMEOUT(), &request);
     888        if (tevent_req_nomem(subreq, req)) {
     889                return tevent_req_post(req, ev);
     890        }
     891        tevent_req_set_callback(subreq, push_database_new_started, req);
     892
     893        return req;
     894}
     895
     896static void push_database_new_started(struct tevent_req *subreq)
     897{
     898        struct tevent_req *req = tevent_req_callback_data(
     899                subreq, struct tevent_req);
     900        struct push_database_new_state *state = tevent_req_data(
     901                req, struct push_database_new_state);
     902        int *err_list;
     903        int ret;
     904        bool status;
     905
     906        status = ctdb_client_control_multi_recv(subreq, &ret, state,
     907                                                &err_list, NULL);
     908        TALLOC_FREE(subreq);
     909        if (! status) {
     910                int ret2;
     911                uint32_t pnn;
     912
     913                ret2 = ctdb_client_control_multi_error(state->pnn_list,
     914                                                       state->count,
     915                                                       err_list, &pnn);
     916                if (ret2 != 0) {
     917                        LOG("control DB_PUSH_START failed for db %s "
     918                            "on node %u, ret=%d\n",
     919                            recdb_name(state->recdb), pnn, ret2);
     920                } else {
     921                        LOG("control DB_PUSH_START failed for db %s, ret=%d\n",
     922                            recdb_name(state->recdb), ret);
     923                }
     924                talloc_free(err_list);
     925
     926                tevent_req_error(req, ret);
     927                return;
     928        }
     929
     930        push_database_new_send_msg(req);
     931}
     932
     933static void push_database_new_send_msg(struct tevent_req *req)
     934{
     935        struct push_database_new_state *state = tevent_req_data(
     936                req, struct push_database_new_state);
     937        struct tevent_req *subreq;
     938        struct ctdb_rec_buffer *recbuf;
     939        struct ctdb_req_message message;
     940        TDB_DATA data;
     941        int ret;
     942
     943        if (state->num_buffers_sent == state->num_buffers) {
     944                struct ctdb_req_control request;
     945
     946                ctdb_req_control_db_push_confirm(&request,
     947                                                 recdb_id(state->recdb));
     948                subreq = ctdb_client_control_multi_send(state, state->ev,
     949                                                        state->client,
     950                                                        state->pnn_list,
     951                                                        state->count,
     952                                                        TIMEOUT(), &request);
     953                if (tevent_req_nomem(subreq, req)) {
     954                        return;
     955                }
     956                tevent_req_set_callback(subreq, push_database_new_confirmed,
     957                                        req);
     958                return;
     959        }
     960
     961        ret = ctdb_rec_buffer_read(state->fd, state, &recbuf);
     962        if (ret != 0) {
     963                tevent_req_error(req, ret);
     964                return;
     965        }
     966
     967        data.dsize = ctdb_rec_buffer_len(recbuf);
     968        data.dptr = talloc_size(state, data.dsize);
     969        if (tevent_req_nomem(data.dptr, req)) {
     970                return;
     971        }
     972
     973        ctdb_rec_buffer_push(recbuf, data.dptr);
     974
     975        message.srvid = state->srvid;
     976        message.data.data = data;
     977
     978        LOG("Pushing buffer %d with %d records for %s\n",
     979            state->num_buffers_sent, recbuf->count, recdb_name(state->recdb));
     980
     981        subreq = ctdb_client_message_multi_send(state, state->ev,
     982                                                state->client,
     983                                                state->pnn_list, state->count,
     984                                                &message);
     985        if (tevent_req_nomem(subreq, req)) {
     986                return;
     987        }
     988        tevent_req_set_callback(subreq, push_database_new_send_done, req);
     989
     990        state->num_records += recbuf->count;
     991
     992        talloc_free(data.dptr);
     993        talloc_free(recbuf);
     994}
     995
     996static void push_database_new_send_done(struct tevent_req *subreq)
     997{
     998        struct tevent_req *req = tevent_req_callback_data(
     999                subreq, struct tevent_req);
     1000        struct push_database_new_state *state = tevent_req_data(
     1001                req, struct push_database_new_state);
     1002        bool status;
     1003        int ret;
     1004
     1005        status = ctdb_client_message_multi_recv(subreq, &ret, NULL, NULL);
     1006        TALLOC_FREE(subreq);
     1007        if (! status) {
     1008                LOG("Sending recovery records failed for %s\n",
     1009                    recdb_name(state->recdb));
     1010                tevent_req_error(req, ret);
     1011                return;
     1012        }
     1013
     1014        state->num_buffers_sent += 1;
     1015
     1016        push_database_new_send_msg(req);
     1017}
     1018
     1019static void push_database_new_confirmed(struct tevent_req *subreq)
     1020{
     1021        struct tevent_req *req = tevent_req_callback_data(
     1022                subreq, struct tevent_req);
     1023        struct push_database_new_state *state = tevent_req_data(
     1024                req, struct push_database_new_state);
     1025        struct ctdb_reply_control **reply;
     1026        int *err_list;
     1027        bool status;
     1028        int ret, i;
     1029        uint32_t num_records;
     1030
     1031        status = ctdb_client_control_multi_recv(subreq, &ret, state,
     1032                                                &err_list, &reply);
     1033        TALLOC_FREE(subreq);
     1034        if (! status) {
     1035                int ret2;
     1036                uint32_t pnn;
     1037
     1038                ret2 = ctdb_client_control_multi_error(state->pnn_list,
     1039                                                       state->count, err_list,
     1040                                                       &pnn);
     1041                if (ret2 != 0) {
     1042                        LOG("control DB_PUSH_CONFIRM failed for %s on node %u,"
     1043                            " ret=%d\n", recdb_name(state->recdb), pnn, ret2);
     1044                } else {
     1045                        LOG("control DB_PUSH_CONFIRM failed for %s, ret=%d\n",
     1046                            recdb_name(state->recdb), ret);
     1047                }
     1048                tevent_req_error(req, ret);
     1049                return;
     1050        }
     1051
     1052        for (i=0; i<state->count; i++) {
     1053                ret = ctdb_reply_control_db_push_confirm(reply[i],
     1054                                                         &num_records);
     1055                if (ret != 0) {
     1056                        tevent_req_error(req, EPROTO);
     1057                        return;
     1058                }
     1059
     1060                if (num_records != state->num_records) {
     1061                        LOG("Node %u received %d of %d records for %s\n",
     1062                            state->pnn_list[i], num_records,
     1063                            state->num_records, recdb_name(state->recdb));
     1064                        tevent_req_error(req, EPROTO);
     1065                        return;
     1066                }
     1067        }
     1068
     1069        talloc_free(reply);
     1070
     1071        LOG("Pushed %d records for db %s\n",
     1072            state->num_records, recdb_name(state->recdb));
     1073
     1074        tevent_req_done(req);
     1075}
     1076
     1077static bool push_database_new_recv(struct tevent_req *req, int *perr)
     1078{
     1079        return generic_recv(req, perr);
     1080}
     1081
     1082/*
     1083 * wrapper for push_database_old and push_database_new
     1084 */
     1085
     1086struct push_database_state {
     1087        bool old_done, new_done;
     1088};
     1089
     1090static void push_database_old_done(struct tevent_req *subreq);
     1091static void push_database_new_done(struct tevent_req *subreq);
     1092
     1093static struct tevent_req *push_database_send(
     1094                        TALLOC_CTX *mem_ctx,
     1095                        struct tevent_context *ev,
     1096                        struct ctdb_client_context *client,
     1097                        uint32_t *pnn_list, int count, uint32_t *caps,
     1098                        struct ctdb_tunable_list *tun_list,
     1099                        struct recdb_context *recdb)
     1100{
     1101        struct tevent_req *req, *subreq;
     1102        struct push_database_state *state;
     1103        uint32_t *old_list, *new_list;
     1104        int old_count, new_count;
     1105        int i;
     1106
     1107        req = tevent_req_create(mem_ctx, &state, struct push_database_state);
     1108        if (req == NULL) {
     1109                return NULL;
     1110        }
     1111
     1112        state->old_done = false;
     1113        state->new_done = false;
     1114
     1115        old_count = 0;
     1116        new_count = 0;
     1117        old_list = talloc_array(state, uint32_t, count);
     1118        new_list = talloc_array(state, uint32_t, count);
     1119        if (tevent_req_nomem(old_list, req) ||
     1120            tevent_req_nomem(new_list,req)) {
     1121                return tevent_req_post(req, ev);
     1122        }
     1123
     1124        for (i=0; i<count; i++) {
     1125                uint32_t pnn = pnn_list[i];
     1126
     1127                if (caps[pnn] & CTDB_CAP_FRAGMENTED_CONTROLS) {
     1128                        new_list[new_count] = pnn;
     1129                        new_count += 1;
     1130                } else {
     1131                        old_list[old_count] = pnn;
     1132                        old_count += 1;
     1133                }
     1134        }
     1135
     1136        if (old_count > 0) {
     1137                subreq = push_database_old_send(state, ev, client,
     1138                                                old_list, old_count, recdb);
     1139                if (tevent_req_nomem(subreq, req)) {
     1140                        return tevent_req_post(req, ev);
     1141                }
     1142                tevent_req_set_callback(subreq, push_database_old_done, req);
     1143        } else {
     1144                state->old_done = true;
     1145        }
     1146
     1147        if (new_count > 0) {
     1148                subreq = push_database_new_send(state, ev, client,
     1149                                                new_list, new_count, recdb,
     1150                                                tun_list->rec_buffer_size_limit);
     1151                if (tevent_req_nomem(subreq, req)) {
     1152                        return tevent_req_post(req, ev);
     1153                }
     1154                tevent_req_set_callback(subreq, push_database_new_done, req);
     1155        } else {
     1156                state->new_done = true;
     1157        }
     1158
     1159        return req;
     1160}
     1161
     1162static void push_database_old_done(struct tevent_req *subreq)
     1163{
     1164        struct tevent_req *req = tevent_req_callback_data(
     1165                subreq, struct tevent_req);
     1166        struct push_database_state *state = tevent_req_data(
     1167                req, struct push_database_state);
     1168        bool status;
     1169        int ret;
     1170
     1171        status = push_database_old_recv(subreq, &ret);
     1172        if (! status) {
     1173                tevent_req_error(req, ret);
     1174                return;
     1175        }
     1176
     1177        state->old_done = true;
     1178
     1179        if (state->old_done && state->new_done) {
     1180                tevent_req_done(req);
     1181        }
     1182}
     1183
     1184static void push_database_new_done(struct tevent_req *subreq)
     1185{
     1186        struct tevent_req *req = tevent_req_callback_data(
     1187                subreq, struct tevent_req);
     1188        struct push_database_state *state = tevent_req_data(
     1189                req, struct push_database_state);
     1190        bool status;
     1191        int ret;
     1192
     1193        status = push_database_new_recv(subreq, &ret);
     1194        if (! status) {
     1195                tevent_req_error(req, ret);
     1196                return;
     1197        }
     1198
     1199        state->new_done = true;
     1200
     1201        if (state->old_done && state->new_done) {
     1202                tevent_req_done(req);
     1203        }
     1204}
     1205
     1206static bool push_database_recv(struct tevent_req *req, int *perr)
     1207{
     1208        return generic_recv(req, perr);
    2711209}
    2721210
     
    2801218        uint32_t *pnn_list;
    2811219        int count;
     1220        uint32_t *caps;
     1221        uint32_t *ban_credits;
    2821222        uint32_t db_id;
    2831223        struct recdb_context *recdb;
     
    2921232                        struct tevent_context *ev,
    2931233                        struct ctdb_client_context *client,
    294                         uint32_t *pnn_list, int count,
    295                         uint32_t db_id, struct recdb_context *recdb)
     1234                        uint32_t *pnn_list, int count, uint32_t *caps,
     1235                        uint32_t *ban_credits, uint32_t db_id,
     1236                        struct recdb_context *recdb)
    2961237{
    2971238        struct tevent_req *req, *subreq;
     
    3091250        state->pnn_list = pnn_list;
    3101251        state->count = count;
     1252        state->caps = caps;
     1253        state->ban_credits = ban_credits;
    3111254        state->db_id = db_id;
    3121255        state->recdb = recdb;
     
    3321275                req, struct collect_highseqnum_db_state);
    3331276        struct ctdb_reply_control **reply;
    334         struct ctdb_req_control request;
    335         struct ctdb_pulldb pulldb;
    3361277        int *err_list;
    3371278        bool status;
     
    3801321            recdb_name(state->recdb), state->max_pnn, max_seqnum);
    3811322
    382         pulldb.db_id = state->db_id;
    383         pulldb.lmaster = CTDB_LMASTER_ANY;
    384 
    385         ctdb_req_control_pull_db(&request, &pulldb);
    386         subreq = ctdb_client_control_send(state, state->ev, state->client,
    387                                           state->max_pnn, TIMEOUT(), &request);
     1323        subreq = pull_database_send(state, state->ev, state->client,
     1324                                    state->max_pnn,
     1325                                    state->caps[state->max_pnn],
     1326                                    state->recdb);
    3881327        if (tevent_req_nomem(subreq, req)) {
    3891328                return;
     
    3991338        struct collect_highseqnum_db_state *state = tevent_req_data(
    4001339                req, struct collect_highseqnum_db_state);
    401         struct ctdb_reply_control *reply;
    402         struct ctdb_rec_buffer *recbuf;
    403         int ret;
    404         bool status;
    405 
    406         status = ctdb_client_control_recv(subreq, &ret, state, &reply);
    407         TALLOC_FREE(subreq);
    408         if (! status) {
    409                 LOG("control PULL_DB failed for %s on node %u, ret=%d\n",
    410                     recdb_name(state->recdb), state->max_pnn, ret);
    411                 tevent_req_error(req, ret);
    412                 return;
    413         }
    414 
    415         ret = ctdb_reply_control_pull_db(reply, state, &recbuf);
    416         if (ret != 0) {
    417                 tevent_req_error(req, EPROTO);
    418                 return;
    419         }
    420 
    421         talloc_free(reply);
    422 
    423         ret = recdb_add(state->recdb, ctdb_client_pnn(state->client), recbuf);
    424         talloc_free(recbuf);
    425         if (! ret) {
    426                 tevent_req_error(req, EIO);
     1340        int ret;
     1341        bool status;
     1342
     1343        status = pull_database_recv(subreq, &ret);
     1344        TALLOC_FREE(subreq);
     1345        if (! status) {
     1346                state->ban_credits[state->max_pnn] += 1;
     1347                tevent_req_error(req, ret);
    4271348                return;
    4281349        }
     
    4331354static bool collect_highseqnum_db_recv(struct tevent_req *req, int *perr)
    4341355{
    435         int err;
    436 
    437         if (tevent_req_is_unix_error(req, &err)) {
    438                 if (perr != NULL) {
    439                         *perr = err;
    440                 }
    441                 return false;
    442         }
    443 
    444         return true;
     1356        return generic_recv(req, perr);
    4451357}
    4461358
     
    4541366        uint32_t *pnn_list;
    4551367        int count;
     1368        uint32_t *caps;
     1369        uint32_t *ban_credits;
    4561370        uint32_t db_id;
    4571371        struct recdb_context *recdb;
     
    4661380                        struct tevent_context *ev,
    4671381                        struct ctdb_client_context *client,
    468                         uint32_t *pnn_list, int count,
    469                         uint32_t db_id, struct recdb_context *recdb)
     1382                        uint32_t *pnn_list, int count, uint32_t *caps,
     1383                        uint32_t *ban_credits, uint32_t db_id,
     1384                        struct recdb_context *recdb)
    4701385{
    4711386        struct tevent_req *req, *subreq;
    4721387        struct collect_all_db_state *state;
    473         struct ctdb_req_control request;
     1388        uint32_t pnn;
    4741389
    4751390        req = tevent_req_create(mem_ctx, &state,
     
    4831398        state->pnn_list = pnn_list;
    4841399        state->count = count;
     1400        state->caps = caps;
     1401        state->ban_credits = ban_credits;
    4851402        state->db_id = db_id;
    4861403        state->recdb = recdb;
    487 
    488         state->pulldb.db_id = db_id;
    489         state->pulldb.lmaster = CTDB_LMASTER_ANY;
    490 
    4911404        state->index = 0;
    4921405
    493         ctdb_req_control_pull_db(&request, &state->pulldb);
    494         subreq = ctdb_client_control_send(state, ev, client,
    495                                           state->pnn_list[state->index],
    496                                           TIMEOUT(), &request);
     1406        pnn = state->pnn_list[state->index];
     1407
     1408        subreq = pull_database_send(state, ev, client, pnn, caps[pnn], recdb);
    4971409        if (tevent_req_nomem(subreq, req)) {
    4981410                return tevent_req_post(req, ev);
     
    5091421        struct collect_all_db_state *state = tevent_req_data(
    5101422                req, struct collect_all_db_state);
    511         struct ctdb_reply_control *reply;
    512         struct ctdb_req_control request;
    513         struct ctdb_rec_buffer *recbuf;
    514         int ret;
    515         bool status;
    516 
    517         status = ctdb_client_control_recv(subreq, &ret, state, &reply);
    518         TALLOC_FREE(subreq);
    519         if (! status) {
    520                 LOG("control PULL_DB failed for %s from node %u, ret=%d\n",
    521                     recdb_name(state->recdb), state->pnn_list[state->index],
    522                     ret);
    523                 tevent_req_error(req, ret);
    524                 return;
    525         }
    526 
    527         ret = ctdb_reply_control_pull_db(reply, state, &recbuf);
    528         if (ret != 0) {
    529                 LOG("control PULL_DB failed for %s, ret=%d\n",
    530                     recdb_name(state->recdb), ret);
    531                 tevent_req_error(req, EPROTO);
    532                 return;
    533         }
    534 
    535         talloc_free(reply);
    536 
    537         status = recdb_add(state->recdb, ctdb_client_pnn(state->client), recbuf);
    538         talloc_free(recbuf);
    539         if (! status) {
    540                 tevent_req_error(req, EIO);
     1423        uint32_t pnn;
     1424        int ret;
     1425        bool status;
     1426
     1427        status = pull_database_recv(subreq, &ret);
     1428        TALLOC_FREE(subreq);
     1429        if (! status) {
     1430                pnn = state->pnn_list[state->index];
     1431                state->ban_credits[pnn] += 1;
     1432                tevent_req_error(req, ret);
    5411433                return;
    5421434        }
     
    5481440        }
    5491441
    550         ctdb_req_control_pull_db(&request, &state->pulldb);
    551         subreq = ctdb_client_control_send(state, state->ev, state->client,
    552                                           state->pnn_list[state->index],
    553                                           TIMEOUT(), &request);
     1442        pnn = state->pnn_list[state->index];
     1443        subreq = pull_database_send(state, state->ev, state->client,
     1444                                    pnn, state->caps[pnn], state->recdb);
    5541445        if (tevent_req_nomem(subreq, req)) {
    5551446                return;
     
    5601451static bool collect_all_db_recv(struct tevent_req *req, int *perr)
    5611452{
    562         int err;
    563 
    564         if (tevent_req_is_unix_error(req, &err)) {
    565                 if (perr != NULL) {
    566                         *perr = err;
    567                 }
    568                 return false;
    569         }
    570 
    571         return true;
     1453        return generic_recv(req, perr);
    5721454}
    5731455
     
    5921474        uint32_t *pnn_list;
    5931475        int count;
     1476        uint32_t *caps;
     1477        uint32_t *ban_credits;
    5941478        uint32_t db_id;
    5951479        bool persistent;
     
    6001484        const char *db_name, *db_path;
    6011485        struct recdb_context *recdb;
    602         struct ctdb_rec_buffer *recbuf;
    603 
    6041486};
    6051487
     
    6191501                                          struct ctdb_tunable_list *tun_list,
    6201502                                          uint32_t *pnn_list, int count,
     1503                                          uint32_t *caps,
     1504                                          uint32_t *ban_credits,
    6211505                                          uint32_t generation,
    6221506                                          uint32_t db_id, bool persistent)
     
    6361520        state->pnn_list = pnn_list;
    6371521        state->count = count;
     1522        state->caps = caps;
     1523        state->ban_credits = ban_credits;
    6381524        state->db_id = db_id;
    6391525        state->persistent = persistent;
     
    8201706                subreq = collect_highseqnum_db_send(
    8211707                                state, state->ev, state->client,
    822                                 state->pnn_list, state->count,
    823                                 state->db_id, state->recdb);
     1708                                state->pnn_list, state->count, state->caps,
     1709                                state->ban_credits, state->db_id,
     1710                                state->recdb);
    8241711        } else {
    8251712                subreq = collect_all_db_send(
    8261713                                state, state->ev, state->client,
    827                                 state->pnn_list, state->count,
    828                                 state->db_id, state->recdb);
     1714                                state->pnn_list, state->count, state->caps,
     1715                                state->ban_credits, state->db_id,
     1716                                state->recdb);
    8291717        }
    8301718        if (tevent_req_nomem(subreq, req)) {
     
    8721760        struct recover_db_state *state = tevent_req_data(
    8731761                req, struct recover_db_state);
    874         struct ctdb_req_control request;
    8751762        int *err_list;
    8761763        int ret;
     
    8981785        }
    8991786
    900         state->recbuf = recdb_records(state->recdb, state, state->destnode);
    901         if (tevent_req_nomem(state->recbuf, req)) {
    902                 return;
    903         }
    904 
    905         TALLOC_FREE(state->recdb);
    906 
    907         ctdb_req_control_push_db(&request, state->recbuf);
    908         subreq = ctdb_client_control_multi_send(state, state->ev,
    909                                                 state->client,
    910                                                 state->pnn_list, state->count,
    911                                                 TIMEOUT(), &request);
     1787        subreq = push_database_send(state, state->ev, state->client,
     1788                                    state->pnn_list, state->count,
     1789                                    state->caps, state->tun_list,
     1790                                    state->recdb);
    9121791        if (tevent_req_nomem(subreq, req)) {
    9131792                return;
     
    9231802                req, struct recover_db_state);
    9241803        struct ctdb_req_control request;
    925         int *err_list;
    926         int ret;
    927         bool status;
    928 
    929         status = ctdb_client_control_multi_recv(subreq, &ret, NULL, &err_list,
    930                                                 NULL);
    931         TALLOC_FREE(subreq);
    932         if (! status) {
    933                 int ret2;
    934                 uint32_t pnn;
    935 
    936                 ret2 = ctdb_client_control_multi_error(state->pnn_list,
    937                                                        state->count,
    938                                                        err_list, &pnn);
    939                 if (ret2 != 0) {
    940                         LOG("control PUSHDB failed for db %s on node %u,"
    941                             " ret=%d\n", state->db_name, pnn, ret2);
    942                 } else {
    943                         LOG("control PUSHDB failed for db %s, ret=%d\n",
    944                             state->db_name, ret);
    945                 }
    946                 tevent_req_error(req, ret);
    947                 return;
    948         }
    949 
    950         TALLOC_FREE(state->recbuf);
     1804        int ret;
     1805        bool status;
     1806
     1807        status = push_database_recv(subreq, &ret);
     1808        TALLOC_FREE(subreq);
     1809        if (! status) {
     1810                tevent_req_error(req, ret);
     1811                return;
     1812        }
     1813
     1814        TALLOC_FREE(state->recdb);
    9511815
    9521816        ctdb_req_control_db_transaction_commit(&request, &state->transdb);
     
    10401904static bool recover_db_recv(struct tevent_req *req)
    10411905{
    1042         int err;
    1043 
    1044         if (tevent_req_is_unix_error(req, &err)) {
    1045                 return false;
    1046         }
    1047 
    1048         return true;
     1906        return generic_recv(req, NULL);
    10491907}
    10501908
     
    10701928        uint32_t *pnn_list;
    10711929        int count;
     1930        uint32_t *caps;
     1931        uint32_t *ban_credits;
    10721932        uint32_t generation;
    10731933        uint32_t db_id;
     
    10841944                                           struct ctdb_tunable_list *tun_list,
    10851945                                           uint32_t *pnn_list, int count,
     1946                                           uint32_t *caps,
     1947                                           uint32_t *ban_credits,
    10861948                                           uint32_t generation)
    10871949{
     
    11191981                substate->pnn_list = pnn_list;
    11201982                substate->count = count;
     1983                substate->caps = caps;
     1984                substate->ban_credits = ban_credits;
    11211985                substate->generation = generation;
    11221986                substate->db_id = dbmap->dbs[i].db_id;
     
    11251989
    11261990                subreq = recover_db_send(state, ev, client, tun_list,
    1127                                          pnn_list, count, generation,
    1128                                          substate->db_id,
     1991                                         pnn_list, count, caps, ban_credits,
     1992                                         generation, substate->db_id,
    11291993                                         substate->persistent);
    11301994                if (tevent_req_nomem(subreq, req)) {
     
    11572021
    11582022        substate->num_fails += 1;
    1159         if (substate->num_fails < 5) {
     2023        if (substate->num_fails < NUM_RETRIES) {
    11602024                subreq = recover_db_send(state, state->ev, substate->client,
    11612025                                         substate->tun_list,
    11622026                                         substate->pnn_list, substate->count,
     2027                                         substate->caps, substate->ban_credits,
    11632028                                         substate->generation, substate->db_id,
    11642029                                         substate->persistent);
     
    12072072 * Run the parallel database recovery
    12082073 *
     2074 * - Get tunables
    12092075 * - Get nodemap
    12102076 * - Get vnnmap
    12112077 * - Get capabilities from all nodes
    1212  * - Get tunables from all nodes
    12132078 * - Get dbmap
    12142079 * - Set RECOVERY_ACTIVE
     
    12292094        struct ctdb_node_map *nodemap;
    12302095        uint32_t *caps;
     2096        uint32_t *ban_credits;
    12312097        struct ctdb_tunable_list *tun_list;
    12322098        struct ctdb_vnn_map *vnnmap;
     
    12342100};
    12352101
     2102static void recovery_tunables_done(struct tevent_req *subreq);
    12362103static void recovery_nodemap_done(struct tevent_req *subreq);
    12372104static void recovery_vnnmap_done(struct tevent_req *subreq);
    12382105static void recovery_capabilities_done(struct tevent_req *subreq);
    1239 static void recovery_tunables_done(struct tevent_req *subreq);
    12402106static void recovery_dbmap_done(struct tevent_req *subreq);
    12412107static void recovery_active_done(struct tevent_req *subreq);
     
    12432109static void recovery_vnnmap_update_done(struct tevent_req *subreq);
    12442110static void recovery_db_recovery_done(struct tevent_req *subreq);
     2111static void recovery_failed_done(struct tevent_req *subreq);
    12452112static void recovery_normal_done(struct tevent_req *subreq);
    12462113static void recovery_end_recovery_done(struct tevent_req *subreq);
     
    12652132        state->destnode = ctdb_client_pnn(client);
    12662133
    1267         ctdb_req_control_get_nodemap(&request);
    1268         subreq = ctdb_client_control_send(mem_ctx, ev, client, state->destnode,
    1269                                           TIMEOUT(), &request);
     2134        ctdb_req_control_get_all_tunables(&request);
     2135        subreq = ctdb_client_control_send(state, state->ev, state->client,
     2136                                          state->destnode, TIMEOUT(),
     2137                                          &request);
    12702138        if (tevent_req_nomem(subreq, req)) {
    12712139                return tevent_req_post(req, ev);
    12722140        }
    1273         tevent_req_set_callback(subreq, recovery_nodemap_done, req);
     2141        tevent_req_set_callback(subreq, recovery_tunables_done, req);
    12742142
    12752143        return req;
    12762144}
    12772145
    1278 static void recovery_nodemap_done(struct tevent_req *subreq)
     2146static void recovery_tunables_done(struct tevent_req *subreq)
    12792147{
    12802148        struct tevent_req *req = tevent_req_callback_data(
     
    12842152        struct ctdb_reply_control *reply;
    12852153        struct ctdb_req_control request;
     2154        int ret;
     2155        bool status;
     2156
     2157        status = ctdb_client_control_recv(subreq, &ret, state, &reply);
     2158        TALLOC_FREE(subreq);
     2159        if (! status) {
     2160                LOG("control GET_ALL_TUNABLES failed, ret=%d\n", ret);
     2161                tevent_req_error(req, ret);
     2162                return;
     2163        }
     2164
     2165        ret = ctdb_reply_control_get_all_tunables(reply, state,
     2166                                                  &state->tun_list);
     2167        if (ret != 0) {
     2168                LOG("control GET_ALL_TUNABLES failed, ret=%d\n", ret);
     2169                tevent_req_error(req, EPROTO);
     2170                return;
     2171        }
     2172
     2173        talloc_free(reply);
     2174
     2175        recover_timeout = state->tun_list->recover_timeout;
     2176
     2177        ctdb_req_control_get_nodemap(&request);
     2178        subreq = ctdb_client_control_send(state, state->ev, state->client,
     2179                                          state->destnode, TIMEOUT(),
     2180                                          &request);
     2181        if (tevent_req_nomem(subreq, req)) {
     2182                return;
     2183        }
     2184        tevent_req_set_callback(subreq, recovery_nodemap_done, req);
     2185}
     2186
     2187static void recovery_nodemap_done(struct tevent_req *subreq)
     2188{
     2189        struct tevent_req *req = tevent_req_callback_data(
     2190                subreq, struct tevent_req);
     2191        struct recovery_state *state = tevent_req_data(
     2192                req, struct recovery_state);
     2193        struct ctdb_reply_control *reply;
     2194        struct ctdb_req_control request;
    12862195        bool status;
    12872196        int ret;
     
    13072216        if (state->count <= 0) {
    13082217                tevent_req_error(req, ENOMEM);
     2218                return;
     2219        }
     2220
     2221        state->ban_credits = talloc_zero_array(state, uint32_t,
     2222                                               state->nodemap->num);
     2223        if (tevent_req_nomem(state->ban_credits, req)) {
    13092224                return;
    13102225        }
     
    14082323                        return;
    14092324                }
    1410         }
    1411 
    1412         talloc_free(reply);
    1413 
    1414         ctdb_req_control_get_all_tunables(&request);
    1415         subreq = ctdb_client_control_send(state, state->ev, state->client,
    1416                                           state->destnode, TIMEOUT(),
    1417                                           &request);
    1418         if (tevent_req_nomem(subreq, req)) {
    1419                 return;
    1420         }
    1421         tevent_req_set_callback(subreq, recovery_tunables_done, req);
    1422 }
    1423 
    1424 static void recovery_tunables_done(struct tevent_req *subreq)
    1425 {
    1426         struct tevent_req *req = tevent_req_callback_data(
    1427                 subreq, struct tevent_req);
    1428         struct recovery_state *state = tevent_req_data(
    1429                 req, struct recovery_state);
    1430         struct ctdb_reply_control *reply;
    1431         struct ctdb_req_control request;
    1432         int ret;
    1433         bool status;
    1434 
    1435         status = ctdb_client_control_recv(subreq, &ret, state, &reply);
    1436         TALLOC_FREE(subreq);
    1437         if (! status) {
    1438                 LOG("control GET_ALL_TUNABLES failed, ret=%d\n", ret);
    1439                 tevent_req_error(req, ret);
    1440                 return;
    1441         }
    1442 
    1443         ret = ctdb_reply_control_get_all_tunables(reply, state,
    1444                                                   &state->tun_list);
    1445         if (ret != 0) {
    1446                 LOG("control GET_ALL_TUNABLES failed, ret=%d\n", ret);
    1447                 tevent_req_error(req, EPROTO);
    1448                 return;
    14492325        }
    14502326
     
    16752551                                  state->dbmap, state->tun_list,
    16762552                                  state->pnn_list, state->count,
     2553                                  state->caps, state->ban_credits,
    16772554                                  state->vnnmap->generation);
    16782555        if (tevent_req_nomem(subreq, req)) {
     
    16952572        TALLOC_FREE(subreq);
    16962573
    1697         LOG("%d databases recovered\n", count);
    1698 
    1699         if (! status) {
    1700                 tevent_req_error(req, EIO);
     2574        LOG("%d of %d databases recovered\n", count, state->dbmap->num);
     2575
     2576        if (! status) {
     2577                uint32_t max_pnn = CTDB_UNKNOWN_PNN, max_credits = 0;
     2578                int i;
     2579
     2580                /* Bans are not enabled */
     2581                if (state->tun_list->enable_bans == 0) {
     2582                        tevent_req_error(req, EIO);
     2583                        return;
     2584                }
     2585
     2586                for (i=0; i<state->count; i++) {
     2587                        uint32_t pnn;
     2588                        pnn = state->pnn_list[i];
     2589                        if (state->ban_credits[pnn] > max_credits) {
     2590                                max_pnn = pnn;
     2591                                max_credits = state->ban_credits[pnn];
     2592                        }
     2593                }
     2594
     2595                /* If pulling database fails multiple times */
     2596                if (max_credits >= NUM_RETRIES) {
     2597                        struct ctdb_req_message message;
     2598
     2599                        LOG("Assigning banning credits to node %u\n", max_pnn);
     2600
     2601                        message.srvid = CTDB_SRVID_BANNING;
     2602                        message.data.pnn = max_pnn;
     2603
     2604                        subreq = ctdb_client_message_send(
     2605                                        state, state->ev, state->client,
     2606                                        ctdb_client_pnn(state->client),
     2607                                        &message);
     2608                        if (tevent_req_nomem(subreq, req)) {
     2609                                return;
     2610                        }
     2611                        tevent_req_set_callback(subreq, recovery_failed_done,
     2612                                                req);
     2613                } else {
     2614                        tevent_req_error(req, EIO);
     2615                }
    17012616                return;
    17022617        }
     
    17112626        }
    17122627        tevent_req_set_callback(subreq, recovery_normal_done, req);
     2628}
     2629
     2630static void recovery_failed_done(struct tevent_req *subreq)
     2631{
     2632        struct tevent_req *req = tevent_req_callback_data(
     2633                subreq, struct tevent_req);
     2634        int ret;
     2635        bool status;
     2636
     2637        status = ctdb_client_message_recv(subreq, &ret);
     2638        TALLOC_FREE(subreq);
     2639        if (! status) {
     2640                LOG("failed to assign banning credits, ret=%d\n", ret);
     2641        }
     2642
     2643        tevent_req_error(req, EIO);
    17132644}
    17142645
     
    17952726static void recovery_recv(struct tevent_req *req, int *perr)
    17962727{
    1797         int err;
    1798 
    1799         if (tevent_req_is_unix_error(req, &err)) {
    1800                 if (perr != NULL) {
    1801                         *perr = err;
    1802                 }
    1803                 return;
    1804         }
     2728        generic_recv(req, perr);
    18052729}
    18062730
  • vendor/current/ctdb/server/ctdb_takeover.c

    r988 r989  
    404404}
    405405
    406 struct takeover_callback_state {
    407         struct ctdb_req_control_old *c;
    408         ctdb_sock_addr *addr;
    409         struct ctdb_vnn *vnn;
    410 };
    411 
    412406struct ctdb_do_takeip_state {
    413407        struct ctdb_req_control_old *c;
     
    502496        CTDB_NO_MEMORY(ctdb, state);
    503497
    504         state->c = talloc_steal(ctdb, c);
     498        state->c = NULL;
    505499        state->vnn   = vnn;
    506500
     
    531525        }
    532526
     527        state->c = talloc_steal(ctdb, c);
    533528        return 0;
    534529}
     
    639634        CTDB_NO_MEMORY(ctdb, state);
    640635
    641         state->c = talloc_steal(ctdb, c);
     636        state->c = NULL;
    642637        state->old = old;
    643638        state->vnn = vnn;
     
    671666        }
    672667
     668        state->c = talloc_steal(ctdb, c);
    673669        return 0;
    674670}
     
    816812}
    817813
    818 /*
    819   kill any clients that are registered with a IP that is being released
    820  */
    821 static void release_kill_clients(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
    822 {
    823         struct ctdb_client_ip *ip;
    824 
    825         DEBUG(DEBUG_INFO,("release_kill_clients for ip %s\n",
    826                 ctdb_addr_to_str(addr)));
    827 
    828         for (ip=ctdb->client_ip_list; ip; ip=ip->next) {
    829                 ctdb_sock_addr tmp_addr;
    830 
    831                 tmp_addr = ip->addr;
    832                 DEBUG(DEBUG_INFO,("checking for client %u with IP %s\n",
    833                         ip->client_id,
    834                         ctdb_addr_to_str(&ip->addr)));
    835 
    836                 if (ctdb_same_ip(&tmp_addr, addr)) {
    837                         struct ctdb_client *client = reqid_find(ctdb->idr,
    838                                                                 ip->client_id,
    839                                                                 struct ctdb_client);
    840                         DEBUG(DEBUG_INFO,("matched client %u with IP %s and pid %u\n",
    841                                 ip->client_id,
    842                                 ctdb_addr_to_str(&ip->addr),
    843                                 client->pid));
    844 
    845                         if (client->pid != 0) {
    846                                 DEBUG(DEBUG_INFO,(__location__ " Killing client pid %u for IP %s on client_id %u\n",
    847                                         (unsigned)client->pid,
    848                                         ctdb_addr_to_str(addr),
    849                                         ip->client_id));
    850                                 kill(client->pid, SIGKILL);
    851                         }
    852                 }
    853         }
    854 }
    855 
    856814static void do_delete_ip(struct ctdb_context *ctdb, struct ctdb_vnn *vnn)
    857815{
     
    862820}
    863821
     822static struct ctdb_vnn *release_ip_post(struct ctdb_context *ctdb,
     823                                        struct ctdb_vnn *vnn,
     824                                        ctdb_sock_addr *addr)
     825{
     826        TDB_DATA data;
     827
     828        /* Send a message to all clients of this node telling them
     829         * that the cluster has been reconfigured and they should
     830         * close any connections on this IP address
     831         */
     832        data.dptr = (uint8_t *)ctdb_addr_to_str(addr);
     833        data.dsize = strlen((char *)data.dptr)+1;
     834        DEBUG(DEBUG_INFO, ("Sending RELEASE_IP message for %s\n", data.dptr));
     835        ctdb_daemon_send_message(ctdb, ctdb->pnn, CTDB_SRVID_RELEASE_IP, data);
     836
     837        ctdb_vnn_unassign_iface(ctdb, vnn);
     838
     839        /* Process the IP if it has been marked for deletion */
     840        if (vnn->delete_pending) {
     841                do_delete_ip(ctdb, vnn);
     842                return NULL;
     843        }
     844
     845        return vnn;
     846}
     847
     848struct release_ip_callback_state {
     849        struct ctdb_req_control_old *c;
     850        ctdb_sock_addr *addr;
     851        struct ctdb_vnn *vnn;
     852        uint32_t target_pnn;
     853};
     854
    864855/*
    865856  called when releaseip event finishes
    866857 */
    867 static void release_ip_callback(struct ctdb_context *ctdb, int status, 
     858static void release_ip_callback(struct ctdb_context *ctdb, int status,
    868859                                void *private_data)
    869860{
    870         struct takeover_callback_state *state =
    871                 talloc_get_type(private_data, struct takeover_callback_state);
    872         TDB_DATA data;
     861        struct release_ip_callback_state *state =
     862                talloc_get_type(private_data, struct release_ip_callback_state);
    873863
    874864        if (status == -ETIME) {
     
    888878        }
    889879
    890         /* send a message to all clients of this node telling them
    891            that the cluster has been reconfigured and they should
    892            release any sockets on this IP */
    893         data.dptr = (uint8_t *)talloc_strdup(state, ctdb_addr_to_str(state->addr));
    894         CTDB_NO_MEMORY_VOID(ctdb, data.dptr);
    895         data.dsize = strlen((char *)data.dptr)+1;
    896 
    897         DEBUG(DEBUG_INFO,(__location__ " sending RELEASE_IP for '%s'\n", data.dptr));
    898 
    899         ctdb_daemon_send_message(ctdb, ctdb->pnn, CTDB_SRVID_RELEASE_IP, data);
    900 
    901         /* kill clients that have registered with this IP */
    902         release_kill_clients(ctdb, state->addr);
    903 
    904         ctdb_vnn_unassign_iface(ctdb, state->vnn);
    905 
    906         /* Process the IP if it has been marked for deletion */
    907         if (state->vnn->delete_pending) {
    908                 do_delete_ip(ctdb, state->vnn);
    909                 state->vnn = NULL;
    910         }
     880        state->vnn->pnn = state->target_pnn;
     881        state->vnn = release_ip_post(ctdb, state->vnn, state->addr);
    911882
    912883        /* the control succeeded */
     
    915886}
    916887
    917 static int ctdb_releaseip_destructor(struct takeover_callback_state *state)
     888static int ctdb_releaseip_destructor(struct release_ip_callback_state *state)
    918889{
    919890        if (state->vnn != NULL) {
     
    932903{
    933904        int ret;
    934         struct takeover_callback_state *state;
     905        struct release_ip_callback_state *state;
    935906        struct ctdb_public_ip *pip = (struct ctdb_public_ip *)indata.dptr;
    936907        struct ctdb_vnn *vnn;
     
    944915                return 0;
    945916        }
    946         vnn->pnn = pip->pnn;
    947917
    948918        /* stop any previous arps */
     
    950920        vnn->takeover_ctx = NULL;
    951921
    952         /* Some ctdb tool commands (e.g. moveip, rebalanceip) send
    953          * lazy multicast to drop an IP from any node that isn't the
    954          * intended new node.  The following causes makes ctdbd ignore
    955          * a release for any address it doesn't host.
     922        /* RELEASE_IP controls are sent to all nodes that should not
     923         * be hosting a particular IP.  This serves 2 purposes.  The
     924         * first is to help resolve any inconsistencies.  If a node
     925         * does unexpectly host an IP then it will be released.  The
     926         * 2nd is to use a "redundant release" to tell non-takeover
     927         * nodes where an IP is moving to.  This is how "ctdb ip" can
     928         * report the (likely) location of an IP by only asking the
     929         * local node.  Redundant releases need to update the PNN but
     930         * are otherwise ignored.
    956931         */
    957932        if (ctdb->tunable.disable_ip_failover == 0 && ctdb->do_checkpublicip) {
     
    961936                                vnn->public_netmask_bits,
    962937                                ctdb_vnn_iface_string(vnn)));
     938                        vnn->pnn = pip->pnn;
    963939                        ctdb_vnn_unassign_iface(ctdb, vnn);
    964940                        return 0;
     
    969945                                           ctdb_addr_to_str(&pip->addr),
    970946                                           vnn->public_netmask_bits));
     947                        vnn->pnn = pip->pnn;
    971948                        return 0;
    972949                }
     
    994971                pip->pnn));
    995972
    996         state = talloc(ctdb, struct takeover_callback_state);
     973        state = talloc(ctdb, struct release_ip_callback_state);
    997974        if (state == NULL) {
    998975                ctdb_set_error(ctdb, "Out of memory at %s:%d",
     
    1002979        }
    1003980
    1004         state->c = talloc_steal(state, c);
    1005         state->addr = talloc(state, ctdb_sock_addr);       
     981        state->c = NULL;
     982        state->addr = talloc(state, ctdb_sock_addr);
    1006983        if (state->addr == NULL) {
    1007984                ctdb_set_error(ctdb, "Out of memory at %s:%d",
     
    1012989        }
    1013990        *state->addr = pip->addr;
     991        state->target_pnn = pip->pnn;
    1014992        state->vnn   = vnn;
    1015993
     
    10351013        /* tell the control that we will be reply asynchronously */
    10361014        *async_reply = true;
     1015        state->c = talloc_steal(state, c);
    10371016        return 0;
    10381017}
     
    17761755        bool can_host_ips;
    17771756
     1757        /* Default timeout for early jump to IPREALLOCATED.  See below
     1758         * for explanation of 3 times... */
     1759        timeout = timeval_current_ofs(3 * ctdb->tunable.takeover_timeout, 0);
     1760
    17781761        /*
    17791762         * ip failover is completely disabled, just send out the
     
    18521835
    18531836        ZERO_STRUCT(ip); /* Avoid valgrind warnings for union */
     1837
     1838        /* Each of the following stages (RELEASE_IP, TAKEOVER_IP,
     1839         * IPREALLOCATED) notionally has a timeout of TakeoverTimeout
     1840         * seconds.  However, RELEASE_IP can take longer due to TCP
     1841         * connection killing, so sometimes needs more time.
     1842         * Therefore, use a cumulative timeout of TakeoverTimeout * 3
     1843         * seconds across all 3 stages.  No explicit expiry checks are
     1844         * needed before each stage because tevent is smart enough to
     1845         * fire the timeouts even if they are in the past.  Initialise
     1846         * this here so it explicitly covers the stages we're
     1847         * interested in but, in particular, not the time taken by the
     1848         * ipalloc().
     1849         */
     1850        timeout = timeval_current_ofs(3 * ctdb->tunable.takeover_timeout, 0);
    18541851
    18551852        /* Send a RELEASE_IP to all nodes that should not be hosting
     
    18751872                        ip.addr = tmp_ip->addr;
    18761873
    1877                         timeout = TAKEOVER_TIMEOUT();
    18781874                        data.dsize = sizeof(ip);
    18791875                        data.dptr  = (uint8_t *)&ip;
     
    19181914                ip.addr = tmp_ip->addr;
    19191915
    1920                 timeout = TAKEOVER_TIMEOUT();
    19211916                data.dsize = sizeof(ip);
    19221917                data.dptr  = (uint8_t *)&ip;
     
    19561951        nodes = list_of_connected_nodes(ctdb, nodemap, tmp_ctx, true);
    19571952        ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_IPREALLOCATED,
    1958                                         nodes, 0, TAKEOVER_TIMEOUT(),
     1953                                        nodes, 0, timeout,
    19591954                                        false, tdb_null,
    19601955                                        NULL, iprealloc_fail_callback,
     
    23772372void ctdb_release_all_ips(struct ctdb_context *ctdb)
    23782373{
    2379         struct ctdb_vnn *vnn;
     2374        struct ctdb_vnn *vnn, *next;
    23802375        int count = 0;
    23812376
     
    23842379        }
    23852380
    2386         for (vnn=ctdb->vnn;vnn;vnn=vnn->next) {
     2381        for (vnn = ctdb->vnn; vnn != NULL; vnn = next) {
     2382                /* vnn can be freed below in release_ip_post() */
     2383                next = vnn->next;
     2384
    23872385                if (!ctdb_sys_have_ip(&vnn->public_address)) {
    23882386                        ctdb_vnn_unassign_iface(ctdb, vnn);
    2389                         continue;
    2390                 }
    2391                 if (!vnn->iface) {
    23922387                        continue;
    23932388                }
     
    24132408
    24142409                ctdb_event_script_args(ctdb, CTDB_EVENT_RELEASE_IP, "%s %s %u",
    2415                                   ctdb_vnn_iface_string(vnn),
    2416                                   ctdb_addr_to_str(&vnn->public_address),
    2417                                   vnn->public_netmask_bits);
    2418                 release_kill_clients(ctdb, &vnn->public_address);
    2419                 ctdb_vnn_unassign_iface(ctdb, vnn);
    2420                 vnn->update_in_flight = false;
     2410                                       ctdb_vnn_iface_string(vnn),
     2411                                       ctdb_addr_to_str(&vnn->public_address),
     2412                                       vnn->public_netmask_bits);
     2413                /* releaseip timeouts are converted to success, so to
     2414                 * detect failures just check if the IP address is
     2415                 * still there...
     2416                 */
     2417                if (ctdb_sys_have_ip(&vnn->public_address)) {
     2418                        DEBUG(DEBUG_ERR,
     2419                              (__location__
     2420                               " IP address %s not released\n",
     2421                               ctdb_addr_to_str(&vnn->public_address)));
     2422                        vnn->update_in_flight = false;
     2423                        continue;
     2424                }
     2425
     2426                vnn = release_ip_post(ctdb, vnn, &vnn->public_address);
     2427                if (vnn != NULL) {
     2428                        vnn->update_in_flight = false;
     2429                }
    24212430                count++;
    24222431        }
  • vendor/current/ctdb/server/ctdb_tunables.c

    r988 r989  
    4242        { "KeepaliveInterval",    5,  offsetof(struct ctdb_tunable_list, keepalive_interval), false },
    4343        { "KeepaliveLimit",       5,  offsetof(struct ctdb_tunable_list, keepalive_limit), false },
    44         { "RecoverTimeout",     120,  offsetof(struct ctdb_tunable_list, recover_timeout), false },
     44        { "RecoverTimeout",      30,  offsetof(struct ctdb_tunable_list, recover_timeout), false },
    4545        { "RecoverInterval",      1,  offsetof(struct ctdb_tunable_list, recover_interval), false },
    4646        { "ElectionTimeout",      3,  offsetof(struct ctdb_tunable_list, election_timeout), false },
     
    9494        { "TDBMutexEnabled", 0, offsetof(struct ctdb_tunable_list, mutex_enabled), false },
    9595        { "LockProcessesPerDB", 200, offsetof(struct ctdb_tunable_list, lock_processes_per_db), false },
     96        { "RecBufferSizeLimit", 1000000, offsetof(struct ctdb_tunable_list, rec_buffer_size_limit), false },
    9697};
    9798
  • vendor/current/ctdb/server/ctdbd.c

    r988 r989  
    179179
    180180        ev = tevent_context_init(NULL);
     181        if (ev == NULL) {
     182                DEBUG(DEBUG_ALERT,("tevent_context_init() failed\n"));
     183                exit(1);
     184        }
    181185        tevent_loop_allow_nesting(ev);
    182186
  • vendor/current/ctdb/server/eventscript.c

    r988 r989  
    697697{
    698698        DLIST_REMOVE(callback->ctdb->script_callbacks, callback);
     699        return 0;
     700}
     701
     702struct schedule_callback_state {
     703        struct ctdb_context *ctdb;
     704        void (*callback)(struct ctdb_context *, int, void *);
     705        void *private_data;
     706        int status;
     707        struct tevent_immediate *im;
     708};
     709
     710static void schedule_callback_handler(struct tevent_context *ctx,
     711                                      struct tevent_immediate *im,
     712                                      void *private_data)
     713{
     714        struct schedule_callback_state *state =
     715                talloc_get_type_abort(private_data,
     716                                      struct schedule_callback_state);
     717
     718        if (state->callback != NULL) {
     719                state->callback(state->ctdb, state->status,
     720                                state->private_data);
     721        }
     722        talloc_free(state);
     723}
     724
     725static int
     726schedule_callback_immediate(struct ctdb_context *ctdb,
     727                            void (*callback)(struct ctdb_context *,
     728                                             int, void *),
     729                            void *private_data,
     730                            int status)
     731{
     732        struct schedule_callback_state *state;
     733        struct tevent_immediate *im;
     734
     735        state = talloc_zero(ctdb, struct schedule_callback_state);
     736        if (state == NULL) {
     737                DEBUG(DEBUG_ERR, (__location__ " out of memory\n"));
     738                return -1;
     739        }
     740        im = tevent_create_immediate(state);
     741        if (im == NULL) {
     742                DEBUG(DEBUG_ERR, (__location__ " out of memory\n"));
     743                talloc_free(state);
     744                return -1;
     745        }
     746
     747        state->ctdb = ctdb;
     748        state->callback = callback;
     749        state->private_data = private_data;
     750        state->status = status;
     751        state->im = im;
     752
     753        tevent_schedule_immediate(im, ctdb->ev,
     754                                  schedule_callback_handler, state);
    699755        return 0;
    700756}
     
    808864        state->child = 0;
    809865
     866        /* Nothing to do? */
     867        if (state->scripts->num_scripts == 0) {
     868                int ret = schedule_callback_immediate(ctdb, callback,
     869                                                      private_data, 0);
     870                talloc_free(state);
     871                if (ret != 0) {
     872                        DEBUG(DEBUG_ERR,
     873                              ("Unable to schedule callback for 0 scripts\n"));
     874                        return 1;
     875                }
     876                return 0;
     877        }
     878
     879        state->scripts->scripts[0].status = fork_child_for_script(ctdb, state);
     880        if (state->scripts->scripts[0].status != 0) {
     881                talloc_free(state);
     882                return -1;
     883        }
     884
    810885        if (call == CTDB_EVENT_MONITOR) {
    811886                ctdb->current_monitor = state;
    812887        }
    813888
     889        ctdb->active_events++;
     890
    814891        talloc_set_destructor(state, event_script_destructor);
    815 
    816         ctdb->active_events++;
    817 
    818         /* Nothing to do? */
    819         if (state->scripts->num_scripts == 0) {
    820                 callback(ctdb, 0, private_data);
    821                 talloc_free(state);
    822                 return 0;
    823         }
    824 
    825         state->scripts->scripts[0].status = fork_child_for_script(ctdb, state);
    826         if (state->scripts->scripts[0].status != 0) {
    827                 /* Callback is called from destructor, with fail result. */
    828                 talloc_free(state);
    829                 return 0;
    830         }
    831892
    832893        if (!timeval_is_zero(&state->timeout)) {
     
    10081069        CTDB_NO_MEMORY(ctdb, state);
    10091070
    1010         state->c = talloc_steal(state, c);
     1071        state->c = NULL;
    10111072
    10121073        DEBUG(DEBUG_NOTICE,("Running eventscripts with arguments %s\n", indata.dptr));
     
    10241085        /* tell ctdb_control.c that we will be replying asynchronously */
    10251086        *async_reply = true;
    1026 
     1087        state->c = talloc_steal(state, c);
    10271088        return 0;
    10281089}
Note: See TracChangeset for help on using the changeset viewer.