public function feedbackAction()
 {
     $this->setNoViewRender(true);
     $hostname = $this->getRequest("hostname", "");
     $ip = $this->getRequest("ip", "");
     $node_whole = $this->getRequest("node_whole", "");
     $idc = $this->getRequest("idc", "");
     $value_md5 = $this->getRequest("value_md5", "");
     $value = $this->getRequest("value", "");
     $update_time = $this->getRequest("update_time", "");
     $data_type = $this->getRequest("data_type", "");
     // 0. get client ip
     $client_ip = self::getClientIp();
     QconfMgrLog::err(__FILE__, __LINE__, "client_ip({$client_ip})" . "hostname({$hostname}), node_whole({$node_whole}), idc({$idc}), value_md5({$value_md5}) or data_type({$data_type})!");
     // 1. validation for parameters
     if ($hostname === "" || $node_whole === "" || $idc === "" || $value_md5 === "" || $data_type === "") {
         //$res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_BAD_ARGS);
         QconfMgrLog::err(__FILE__, __LINE__, "hostname({$hostname}), node_whole({$node_whole}), idc({$idc}), value_md5({$value_md5}) or data_type({$data_type}) is NULL!");
         echo InfoDescUtil::ERR_BAD_ARGS;
         return;
     }
     $md5_len = strlen($value_md5);
     if ($md5_len != 32) {
         //$res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_MD5_VALUE);
         QconfMgrLog::err(__FILE__, __LINE__, "Error length value_md5(value_md5) : {$md5_len}!");
         echo InfoDescUtil::ERR_MD5_VALUE;
         return;
     }
     $format_time = date('Y-m-d H:i:s', $update_time);
     if ($format_time === FALSE) {
         QconfMgrLog::err(__FILE__, __LINE__, "error update_time format: {$update_time}");
         //$res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_BAD_ARGS);
         echo InfoDescUtil::ERR_UPDATE_TIME;
         return;
     }
     if ($data_type != InfoDescUtil::QCONF_DATA_TYPE_NODE && $data_type != InfoDescUtil::QCONF_DATA_TYPE_SERVICE) {
         QconfMgrLog::err(__FILE__, __LINE__, "error data_type: {$data_type}");
         //$res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_BAD_ARGS);
         echo InfoDescUtil::ERR_DATA_TYPE;
         return;
     }
     if (!ZkConf::isLegalIdc($idc)) {
         QconfMgrLog::err(__FILE__, __LINE__, "error idc: {$idc}");
         $res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_IDC_NOT_EXIST);
         echo InfoDescUtil::ERR_IDC_NOT_EXIST;
         return;
     }
     // 2.distinguish situation need add new item and modify old item
     $fd_item = FeedbackServ::checkFeedback($hostname, $node_whole, $idc, $data_type);
     $result = FALSE;
     if ($fd_item === FALSE) {
         //add new item
         $retry_time = 0;
         while ($result === FALSE && $retry_time < InfoDescUtil::MYSQL_MAX_RETRY_TIME) {
             $result = FeedbackServ::addFeedback($hostname, $ip, $node_whole, $idc, $data_type, $value_md5, $value, $format_time);
             if ($retry_time++ > 0) {
                 QconfMgrLog::err(__FILE__, __LINE__, "retry {$retry_time} to add feedback with hostname({$hostname})" . " node_whole({$node_whole}) idc({$idc}), data_type({$data_type})!");
             }
         }
         if ($result != FALSE) {
             FeedbackOpServ::recordOp(InfoDescUtil::OP_TYPE_FEEDBACK_ADD, $hostname, $node_whole, $idc, $data_type, $value_md5, $format_time);
         }
     } else {
         $old_update_time = $fd_item["update_time"];
         if ($update_time < strtotime($old_update_time)) {
             QconfMgrLog::err(__FILE__, __LINE__, "update_time early than the last one, discard hostname({$hostname})," . " node_whole({$node_whole}) idc({$idc}), data_type({$data_type})!");
             $result = TRUE;
         } else {
             $feedback_id = $fd_item["feedback_id"];
             $retry_time = 0;
             while ($result === FALSE && $retry_time < InfoDescUtil::MYSQL_MAX_RETRY_TIME) {
                 $result = FeedbackServ::modifyFeedback($feedback_id, $ip, $value_md5, $value, $format_time);
                 if ($retry_time++ > 0) {
                     QconfMgrLog::err(__FILE__, __LINE__, "retry {$retry_time} to modify feedback with hostname({$hostname})" . " node_whole({$node_whole}) idc({$idc}), data_type({$data_type})!");
                 }
             }
             if ($result != FALSE) {
                 FeedbackOpServ::recordOp(InfoDescUtil::OP_TYPE_FEEDBACK_MODIFY, $hostname, $node_whole, $idc, $data_type, $value_md5, $format_time);
             }
         }
     }
     // 3. record feedback failed
     if ($result === FALSE) {
         QconfMgrLog::err(__FILE__, __LINE__, "Failed to record feedback for hostname({$hostname}),\n                node_whole({$node_whole}), idc({$idc})!");
         echo InfoDescUtil::ERR_MYSQL_FAIL;
         return;
     }
     echo InfoDescUtil::QCONF_OK;
     return;
 }
 public function deleteFeedbackAction()
 {
     $feedback_id = $this->getRequest("feedback_id", "");
     // 1. check parameters
     if ($feedback_id === "") {
         $res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_BAD_ARGS);
         QconfMgrLog::err(__FILE__, __LINE__, "parameter feedback_id is null!");
         echo json_encode($res);
         return;
     }
     // 2. delete feedback from database
     $feedback = FeedbackServ::getFeedback($feedback_id);
     if ($feedback === FALSE || empty($feedback)) {
         QconfMgrLog::err(__FILE__, __LINE__, "get feedback failed of feedback({$feedback_id})");
         $res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_FEEDBACK_NOT_EXIST);
         echo json_encode($res);
         return;
     }
     $delete_res = FeedbackServ::deleteFeedback($feedback_id);
     if ($delete_res === FALSE) {
         $res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_MYSQL_FAIL);
         QconfMgrLog::err(__FILE__, __LINE__, "failed to delete feedback({$feedback_id})");
         echo json_encode($res);
         return;
     }
     // 3. record delete operation
     $update_time = date('Y-m-d H:i:s', time());
     $fd_op_res = FeedbackOpServ::recordOp(InfoDescUtil::OP_TYPE_FEEDBACK_DELETE, $feedback["hostname"], $feedback["node_whole"], $feedback["idc"], $feedback["data_type"], $feedback["value_md5"], $update_time);
     if ($fd_op_res === FALSE) {
         QconfMgrLog::err(__FILE__, __LINE__, "failed to feedback op of feedback({$feedback_id})");
     }
     // 4. return result
     $res = array("errno" => "0", "errmsg" => "", "data" => "");
     $json = json_encode($res);
     echo $json;
 }
 private function deleteNode($db_node_whole, $main_buss_id, $idc, $op_user, $zk_web, $del_flags)
 {
     $node = NodeServ::getNodeByNodeWhole($db_node_whole, $main_buss_id);
     if ($node === FALSE) {
         return InfoDescUtil::ERR_NODE_NOT_EXIST;
     }
     $db_node_type = $node["node_type_code"];
     $sub_buss_id = $node["sub_buss_id"];
     // 1. check whether current node has sub nodes
     $qconf_node_path = PathUtil::getQconfPath($db_node_whole);
     $children = -1;
     $retry_time = 0;
     while ($children === -1 && $retry_time <= InfoDescUtil::ZK_MAX_RETRY_TIME) {
         QconfMgrLog::err(__FILE__, __LINE__, "retry {$retry_time} of " . InfoDescUtil::ZK_MAX_RETRY_TIME . " to get children of {$db_node_whole} on {$idc}");
         $children = $zk_web->get_children($qconf_node_path);
         $retry_time++;
     }
     if ($children === -1) {
         QconfMgrLog::err(__FILE__, __LINE__, "Failed to get children of {$db_node_whole} on {$idc}");
         return InfoDescUtil::ERR_ZOOKEEPER_FAIL;
     }
     // 2. delete children nodes or services if needed
     if (count($children) > 0) {
         if ($del_flags === InfoDescUtil::DELETE_TYPE_WHOLE) {
             if ($db_node_type === InfoDescUtil::NODE_TYPE_SERV_FATHER) {
                 $clear_ret = ServiceController::clearServiceWithLink($zk_web, $db_node_whole, $idc, $main_buss_id, $sub_buss_id, $op_user);
                 if ($clear_ret != InfoDescUtil::QCONF_OK) {
                     QconfMgrLog::err(__FILE__, __LINE__, "Failed to clear services of {$db_node_whole} on {$idc}");
                     return $clear_ret;
                 }
             } else {
                 // delete include children
                 foreach ($children as $child) {
                     $child_node_whole = PathUtil::unionPath($db_node_whole, $child);
                     $del_ret = self::deleteNode($child_node_whole, $main_buss_id, $idc, $op_user, $zk_web, InfoDescUtil::DELETE_TYPE_WHOLE);
                     if ($del_ret != InfoDescUtil::QCONF_OK) {
                         QconfMgrLog::err(__FILE__, __LINE__, "Failed to delete children of {$db_node_whole} on {$idc}");
                         return $del_ret;
                     }
                 }
             }
         } else {
             // delete only self
             QconfMgrLog::err(__FILE__, __LINE__, "Exist children nodes of {$db_node_whole} on {$idc}");
             return InfoDescUtil::ERR_SUB_NODE_NOT_NULL;
         }
     }
     // 3. delete conf from zookeeper
     if ($db_node_type === InfoDescUtil::NODE_TYPE_SERV_FATHER) {
         $ret = -1;
         $retry_time = 0;
         while ($ret === -1 && $retry_time <= InfoDescUtil::ZK_MAX_RETRY_TIME) {
             QconfMgrLog::err(__FILE__, __LINE__, "retry {$retry_time} of " . InfoDescUtil::ZK_MAX_RETRY_TIME . " to delete group path for {$db_node_whole} on {$idc}");
             $ret = $zk_web->delete_group_path($qconf_node_path);
             $retry_time++;
         }
     } else {
         $ret = -1;
         $retry_time = 0;
         while ($ret === -1 && $retry_time <= InfoDescUtil::ZK_MAX_RETRY_TIME) {
             QconfMgrLog::err(__FILE__, __LINE__, "retry {$retry_time} of " . InfoDescUtil::ZK_MAX_RETRY_TIME . " to delete {$db_node_whole} on {$idc}");
             $ret = $zk_web->delete_conf($qconf_node_path);
             $retry_time++;
         }
     }
     if ($ret === -1) {
         OpServ::insert(InfoDescUtil::OP_TYPE_DEL, $db_node_whole, $idc, InfoDescUtil::OP_STATUS_ZOO_FAILED, $main_buss_id, $sub_buss_id, $op_user, "");
         return InfoDescUtil::ERR_ZOOKEEPER_FAIL;
     }
     // 4. delete in mysql
     $ret = NodeServ::delNodeByIdc($node["node_id"], $idc);
     if ($ret === TRUE && $node["node_level"] == 1) {
         $ret = PermServ::delPermByIdc(trim($db_node_whole, "\\/"), $main_buss_id, $idc);
         if ($ret === TRUE) {
             // notify admins
             AdminConf::notifyAdmin("Delete root node " . $db_node_whole . " for {$op_user} on {$idc}", $op_user, FALSE);
         }
     }
     if ($ret === -1) {
         OpServ::insert(InfoDescUtil::OP_TYPE_DEL, $db_node_whole, $idc, InfoDescUtil::OP_STATUS_MYSQL_FAILED, $main_buss_id, $sub_buss_id, $op_user, "");
         QconfMgrLog::err(__FILE__, __LINE__, "failed to delete {$db_node_whole} from {$idc} in mysql");
         return InfoDescUtil::ERR_MYSQL_FAIL;
     }
     // 6. delete the feedback items
     $fd_res = FeedbackServ::deleteFeedbackByNode($qconf_node_path, $idc);
     if ($fd_res === FALSE) {
         QconfMgrLog::err(__FILE__, __LINE__, "failed to delete feedbacks of qconf_node_path({$qconf_node_path}), idc({$idc})");
     } else {
         $update_time = date('Y-m-d H:i:s', time());
         $fd_op_res = FeedbackOpServ::recordOp(InfoDescUtil::OP_TYPE_FEEDBACK_DELETE_BY_NODE, "", $qconf_node_path, $idc, "", "", $update_time);
         if ($fd_op_res === FALSE) {
             QconfMgrLog::err(__FILE__, __LINE__, "failed to add feedback operation of qconf_node_path({$qconf_node_path}), idc({$idc})");
         }
     }
     // 7. delete normal user permision
     if (trim($node["idc"], ",") === $idc) {
         // last idc of the node has been deleted
         $delete_res = UserPermServ::deleteNormalByDeleteOp($db_node_whole);
         if ($delete_res === FALSE) {
             QconfMgrLog::err(__FILE__, __LINE__, "failed to delete user perm items on db_node_whole({$db_node_whole})");
             OpServ::insert(InfoDescUtil::OP_TYPE_USER_PERM_NORMAL_DELETE, $db_node_whole, $idc, InfoDescUtil::OP_STATUS_MYSQL_FAILED, $main_buss_id, $sub_buss_id, $op_user, "delete all user perm on {$db_node_whole} failed");
         } else {
             QconfMgrLog::err(__FILE__, __LINE__, "delete all normal perm items on db_node_whole({$db_node_whole})");
             OpServ::insert(InfoDescUtil::OP_TYPE_USER_PERM_NORMAL_DELETE, $db_node_whole, $idc, InfoDescUtil::OP_STATUS_SUCCESS, $main_buss_id, $sub_buss_id, $op_user, "delete all user perm on {$db_node_whole} success");
         }
     }
     OpServ::insert(InfoDescUtil::OP_TYPE_DEL, $db_node_whole, $idc, InfoDescUtil::OP_STATUS_SUCCESS, $main_buss_id, $sub_buss_id, $op_user, "");
     return InfoDescUtil::QCONF_OK;
 }