/**
  * Makes a general query to RODS server. Think it as an SQL. "select foo from sometab where bar = '3'". In this example, foo is specified by "$select", bar and "= '3'" are speficed by condition.
  * @param RODSGenQueSelFlds $select the fields (names) to be returned/interested. There can not be more than 50 input fields. For example:"COL_COLL_NAME" means collection-name.
  * @param RODSGenQueConds $condition  All fields are defined in RodsGenQueryNum.inc.php and RodsGenQueryKeyWd.inc.php
  * @param integer $start result start from which row.
  * @param integer $limit up to how many rows should the result contain. If -1 is passed, all available rows will be returned
  * @return RODSGenQueResults
  * Note: This function is very low level. It's not recommended for beginners.
  */
 public function query(RODSGenQueSelFlds $select, RODSGenQueConds $condition, $start = 0, $limit = -1)
 {
     if ($select->getCount() < 1 || $select->getCount() > 50) {
         throw new RODSException("Only 1-50 fields are supported", 'PERR_USER_INPUT_ERROR');
     }
     // contruct select packet (RP_InxIvalPair $selectInp), and condition packets
     $select_pk = $select->packetize();
     $cond_pk = $condition->packetize();
     $condkw_pk = $condition->packetizeKW();
     // determin max number of results per query
     if ($limit > 0 && $limit < 500) {
         $max_result_per_query = $limit;
     } else {
         $max_result_per_query = 500;
     }
     $num_fetched_rows = 0;
     $continueInx = 0;
     $results = new RODSGenQueResults();
     do {
         // construct RP_GenQueryInp packet
         $options = 1 | $GLOBALS['PRODS_GENQUE_NUMS']['RETURN_TOTAL_ROW_COUNT'];
         $genque_input_pk = new RP_GenQueryInp($max_result_per_query, $continueInx, $condkw_pk, $select_pk, $cond_pk, $options, $start);
         // contruce a new API request message, with type GEN_QUERY_AN
         $msg = new RODSMessage("RODS_API_REQ_T", $genque_input_pk, $GLOBALS['PRODS_API_NUMS']['GEN_QUERY_AN']);
         fwrite($this->conn, $msg->pack());
         // send it
         // get value back
         $msg_resv = new RODSMessage();
         $intInfo = $msg_resv->unpack($this->conn);
         if ($intInfo < 0) {
             if (RODSException::rodsErrCodeToAbbr($intInfo) == 'CAT_NO_ROWS_FOUND') {
                 break;
             }
             throw new RODSException("RODSConn::query has got an error from the server", $GLOBALS['PRODS_ERR_CODES_REV']["{$intInfo}"]);
         }
         $genque_result_pk = $msg_resv->getBody();
         $num_row_added = $results->addResults($genque_result_pk);
         $continueInx = $genque_result_pk->continueInx;
         $start = $start + $results->getNumRow();
     } while ($continueInx > 0 && ($results->getNumRow() < $limit || $limit < 0));
     // Make sure and close the query if there are any results left.
     if ($continueInx > 0) {
         $msg->getBody()->continueInx = $continueInx;
         $msg->getBody()->maxRows = -1;
         // tells the server to close the query
         fwrite($this->conn, $msg->pack());
         $msg_resv = new RODSMessage();
         $intInfo = $msg_resv->unpack($this->conn);
         if ($intInfo < 0) {
             throw new RODSException("RODSConn::query has got an error from the server", $GLOBALS['PRODS_ERR_CODES_REV']["{$intInfo}"]);
         }
     }
     return $results;
 }
 public static function packConnectMsg($user, $proxy_user, $zone, $relVersion = RODS_REL_VERSION, $apiVersion = RODS_API_VERSION, $option = NULL)
 {
     $msgbody = new RP_StartupPack($user, $proxy_user, $zone, $relVersion, $apiVersion . $option);
     $rods_msg = new RODSMessage("RODS_CONNECT_T", $msgbody);
     return $rods_msg->pack();
 }