不在C ++程序中使用libpq检索NOTIFY

时间:2013-12-10 12:56:44

标签: c++ database postgresql ros libpq

我正在增强ROS(机器人操作系统)堆栈sql_database,以便能够处理postgresqls LISTEN和NOTIFY命令。如上所述,我在C ++程序中使用Ubuntu12.04上的libpq版本9.1.10-0。 但由于某些原因,我无法检索到NOTIFY。

我知道,有一个例子(例28-2。libpq示例程序2)并且它工作得很好。我玩了很长时间,并尝试尽可能准确地将其复制到我的代码中,并以某种方式更改示例代码,使其更类似于我遇到问题的代码。但这对我的问题没有帮助。

我可以在示例程序和手动登录数据库中收到通知,但不能在我想要使用的代码中收到通知。

我还尝试了什么:

  • 连接到其他数据库 - 没有改变任何内容。
  • 执行COMMIT;命令后执行LISTEN <channel>;。但由于我没有公开交易,这导致了预期的警告。
  • PQconsumeInput(connection_);之前检查连接是否已经死亡 - 它是纯粹的活着
  • 在同一个函数中执行LISTEN命令,我正在检查NOTIFY(使用断点触发其间的NOTIFY) - 没有改变任何内容。

始终使用NOTIFY <channel>;

手动触发NOTIFY

代码结构

这里也可以看到代码on github(在不稳定的分支上):

  • 类PostgresqlDatabase(在sql_interface-&gt; database_interface-&gt; github上的src)
    该类保存连接PGconn并提供

    之类的任务
     bool listenToChannel(std::string channel);
    

    该类的主要目的是抽象sql查询,以便ROS程序员不再需要关心它们。

  • class databaseBinding
    它是ROS和数据库功能之间的粘合剂。它包含一个PostgresqlDatabase对象,用于获取数据库连接并调用任务。

  • 主要功能
    做以下事情

    1. 做一些ROS初始化的东西
    2. 创建一个databaseBinding对象,该对象将初始化PostgresqlDatabase对象,该对象与我的数据库建立连接
    3. 调用PostgresqlDatabase::listenToChannel(std::string channel) - 函数
    4. 使用PostgresqlDatabase::checkNotify(notification &no) - 函数
    5. 定期进行循环检查NOTIFY

一些代码

检查NOTIFY

checkNotify函数,每秒触发约5次:

/*! Checks for a received NOTIFY and returns it. */
bool PostgresqlDatabase::checkNotify(notification &no)
{
  PGnotify   *notify;
  PQconsumeInput(connection_);
  if ((notify = PQnotifies(connection_)) != NULL)
    {
    no.channel = notify->relname;
    no.sending_pid = notify->be_pid;
    no.payload = notify->extra;
    PQfreemem(notify);
    return true;
    } else
    {
    no.channel = "";
    no.sending_pid = 0;
    no.payload = "";
    PQfreemem(notify);
    return false;
    }
}

收听频道

/*! Listens to a specified channel using the Postgresql LISTEN-function.*/
bool PostgresqlDatabase::listenToChannel(std::string channel) {
  //look, if we're already listening to the channel in our list
  if (std::find(channels_.begin(),channels_.end(),channel) == channels_.end() )
    {
      std::string query = "LISTEN " + channel;
      PGresultAutoPtr result = PQexec(connection_,query.c_str());
      if (PQresultStatus(*result) != PGRES_COMMAND_OK)
          {
              ROS_WARN("LISTEN command failed: %s", PQerrorMessage(connection_));
              return false;
          }
      ROS_INFO("Now listening to channel \"%s\"",channel.c_str());
      channels_.push_back(channel);
      return true;
    }
  ROS_INFO("We are already listening to channel \"%s\" - nothing to be done",channel.c_str());
  return true;
}

1 个答案:

答案 0 :(得分:3)

事实证明,连接有问题。 它是用该代码创建的:

void PostgresqlDatabase::pgMDBconstruct(std::string host, std::string port, 
std::string user, std::string password, std::string dbname )
{
  std::string conn_info = "host=" + host + " port=" + port +
    " user=" + user + " password=" + password + " dbname=" + dbname;
  connection_= PQconnectdb(conn_info.c_str());
  if (PQstatus(connection_)!=CONNECTION_OK)
  {
    ROS_ERROR("Database connection failed with error message: %s", PQerrorMessage(connection_));
  }
}

使用host=192.168.10.100, port=5432, user=turtlebot, password= , dbname=rosdb.
但是空的用户名不满足PQconnectdb的使用,由于某些解析原因,它导致它登录到数据库“turtlebot”。不幸的是,该数据库存在于我的服务器上。当然 - 它没有在“rosdb”数据库中发送任何通知并且连接良好。

对我来说,这是多么尴尬和不幸的行为。