Implement dinitctl restart, addresses #14
authorDavin McCall <davmac@davmac.org>
Sat, 27 Jul 2019 10:45:29 +0000 (20:45 +1000)
committerDavin McCall <davmac@davmac.org>
Sat, 27 Jul 2019 10:45:29 +0000 (20:45 +1000)
src/control.cc
src/dinitctl.cc
src/includes/service.h

index e2e8d603b8c1687568155256f89c6497a08fd63b..e4eb578aaa69b2e3c57b8c1d61a194b436ff4597 100644 (file)
@@ -184,7 +184,7 @@ bool control_conn_t::check_dependents(service_record *service, bool &had_depende
     size_t num_depts = 0;
 
     for (service_dep *dep : service->get_dependents()) {
-        if (dep->dep_type == dependency_type::REGULAR) {
+        if (dep->dep_type == dependency_type::REGULAR && dep->holding_acq) {
             num_depts++;
             // find or allocate a service handle
             handle_t dept_handle = allocate_service_handle(dep->get_from());
@@ -223,7 +223,7 @@ bool control_conn_t::process_start_stop(int pktType)
     }
     
     // 1 byte: packet type
-    // 1 byte: pin in requested state (0 = no pin, 1 = pin)
+    // 1 byte: flags eg pin in requested state (0 = no pin, 1 = pin)
     // 4 bytes: service handle
     
     bool do_pin = ((rbuf[1] & 1) == 1);
@@ -258,6 +258,12 @@ bool control_conn_t::process_start_stop(int pktType)
         {
             // force service to stop
             bool gentle = ((rbuf[1] & 2) == 2);
+            bool do_restart = ((rbuf[1] & 4) == 4);
+            bool is_active = service->is_marked_active();
+            if (do_restart && services->is_shutting_down()) {
+                ack_buf[0] = DINIT_RP_NAK;
+                break;
+            }
             if (gentle) {
                 // Check dependents; return appropriate response if any will be affected
                 bool has_dependents;
@@ -273,7 +279,13 @@ bool control_conn_t::process_start_stop(int pktType)
             service->stop(true);
             service->forced_stop();
             services->process_queues();
-            if (service->get_state() == service_state_t::STOPPED) ack_buf[0] = DINIT_RP_ALREADYSS;
+            service_state_t wanted_state = service_state_t::STOPPED;
+            if (do_restart) {
+                service->start(is_active);
+                wanted_state = service_state_t::STARTED;
+                services->process_queues();
+            }
+            if (service->get_state() == wanted_state) ack_buf[0] = DINIT_RP_ALREADYSS;
             break;
         }
         case DINIT_CP_WAKESERVICE:
index e81019904fc9240d0b96b729e9b44ac110bd76e5..9404335b98f732c9244fff7bf10e2a5634662b30 100644 (file)
@@ -63,6 +63,7 @@ enum class command_t {
     START_SERVICE,
     WAKE_SERVICE,
     STOP_SERVICE,
+    RESTART_SERVICE,
     RELEASE_SERVICE,
     UNPIN_SERVICE,
     UNLOAD_SERVICE,
@@ -132,7 +133,7 @@ int main(int argc, char **argv)
                 }
                 service_name = argv[i];
             }
-            else if ((command == command_t::STOP_SERVICE)
+            else if ((command == command_t::STOP_SERVICE || command == command_t::RESTART_SERVICE)
                     && (strcmp(argv[i], "--force") == 0 || strcmp(argv[i], "-f") == 0)) {
                 do_force = true;
             }
@@ -151,6 +152,9 @@ int main(int argc, char **argv)
             else if (strcmp(argv[i], "stop") == 0) {
                 command = command_t::STOP_SERVICE;
             }
+            else if (strcmp(argv[i], "restart") == 0) {
+                command = command_t::RESTART_SERVICE;
+            }
             else if (strcmp(argv[i], "release") == 0) {
                 command = command_t::RELEASE_SERVICE;
             }
@@ -507,6 +511,7 @@ static int start_stop_service(int socknum, cpbuffer_t &rbuffer, const char *serv
     int pcommand = 0;
     switch (command) {
         case command_t::STOP_SERVICE:
+        case command_t::RESTART_SERVICE:  // stop, and then start
             pcommand = DINIT_CP_STOPSERVICE;
             break;
         case command_t::RELEASE_SERVICE:
@@ -528,11 +533,16 @@ static int start_stop_service(int socknum, cpbuffer_t &rbuffer, const char *serv
         char buf[2 + sizeof(handle)];
         buf[0] = pcommand;
         buf[1] = (do_pin ? 1 : 0) | ((pcommand == DINIT_CP_STOPSERVICE && !do_force) ? 2 : 0);
+        if (command == command_t::RESTART_SERVICE) {
+            buf[1] |= 4;
+        }
         memcpy(buf + 2, &handle, sizeof(handle));
         write_all_x(socknum, buf, 2 + sizeof(handle));
         
         wait_for_reply(rbuffer, socknum);
-        if (rbuffer[0] == DINIT_RP_ALREADYSS) {
+        auto reply_pkt_h = rbuffer[0];
+        rbuffer.consume(1); // consume header
+        if (reply_pkt_h == DINIT_RP_ALREADYSS) {
             bool already = (state == wanted_state);
             if (verbose) {
                 cout << "Service " << (already ? "(already) " : "")
@@ -540,11 +550,10 @@ static int start_stop_service(int socknum, cpbuffer_t &rbuffer, const char *serv
             }
             return 0; // success!
         }
-        if (rbuffer[0] == DINIT_RP_DEPENDENTS && pcommand == DINIT_CP_STOPSERVICE) {
+        if (reply_pkt_h == DINIT_RP_DEPENDENTS && pcommand == DINIT_CP_STOPSERVICE) {
             cerr << "dinitctl: Cannot stop service due to the following dependents:\n"
                     "(Only direct dependents are listed. Exercise caution before using '--force' !!)\n";
             // size_t number, N * handle_t handles
-            rbuffer.consume(1);  // packet header
             size_t number;
             rbuffer.fill_to(socknum, sizeof(number));
             rbuffer.extract(&number, 0, sizeof(number));
@@ -566,11 +575,10 @@ static int start_stop_service(int socknum, cpbuffer_t &rbuffer, const char *serv
             cerr << "\n";
             return 1;
         }
-        if (rbuffer[0] != DINIT_RP_ACK) {
-            cerr << "dinitctl: Protocol error." << endl;
+        if (reply_pkt_h != DINIT_RP_ACK && reply_pkt_h != DINIT_RP_ALREADYSS) {
+            cerr << "dinitctl: protocol error." << endl;
             return 1;
         }
-        rbuffer.consume(1);
     }
 
     if (! wait_for_service) {
index 487d976a43d70a01fcc454fe1238407357e8a860..64ad50ddd8775941ae0a45f57962fb71ba0217b7 100644 (file)
@@ -459,6 +459,12 @@ class service_record
         return desired_state;
     }
 
+    // Is the service explicitly marked active?
+    bool is_marked_active() noexcept
+    {
+        return start_explicit;
+    }
+
     // Set logfile, should be done before service is started
     void set_log_file(const string &logfile)
     {