我的站点

一个系统软件工程师的随手涂鸦

Month: 十二月 2014

Redis从2.8.12版本开始支持“ROLE”命令

今天才知道,Redis2.8.12版本开始支持“ROLE”命令了。通过“ROLE”命令,可以得到当前Redis的角色是“master”,“slave”或者“sentinel”。回想我们一年前做Redis监控程序时,还要通过“info”命令得到整个Redis状态,然后再解析“Role”这个关键字,才能得到是什么角色,实在有点麻烦。如果有机会,应该升级一下监控程序,一旦发现是2.8.12版本,就直接用“ROLE”命令好了。

2014年终总结

2014年就要走完了,是时候总结一下了:
(1)chinadtrace:申请的第一个微信公众号,建立了第一个介绍DTrace的中文网站:http://chinadtrace.org/
(2)8月昆山之行:一场说走就走的旅行
(3)100个gdb小技巧:与hellogcc伙伴们合作的项目。历时半年,今天发布1.0版本。电子书下载地址
(4)公司被并购:将来适当的时候会详细写一下这段过程;
(5)拥有了属于自己的域名:http://nanxiao.me/
(6)为开源项目redisunixODBC贡献patch;
(7)十一之行:难忘的回家之旅
(8)在影院看了两部没白花钱的电影:《白日焰火》和《黄金时代》;
(9)阅读了几本还不错的书;
(10)享受到了4G网络。

100个gdb小技巧(v1.0).pdf

hellogcc于今年6月份开启《100个gdb小技巧》这个项目,我便参与其中。截至到这周末,一共收集了100个实用的gdb小技巧。我利用这个周末时间,把它制作成了一本pdf的电子书,方便大家下载和使用。当然,100不是终点,未来这个项目还会发展下去,还会有2.03.0的版本出来。Stay tuned!

P.S.:下载地址

unixODBC驱动链接的数据库客户端和程序直接链接的数据库客户端库一定要一致

这两天调试了一个诡异的问题,使用unixODBC连接MySQL数据库,最后程序core dumpMySQL client代码的fill_ird_data_lengths函数:

void fill_ird_data_lengths(DESC *ird, ulong *lengths, uint fields)
{
  ......
  assert(fields == ird->count);
}

fileds是一个很离谱的数,一看就像是内存值被破坏了。

经过艰苦的单步调试,最后查出的问题是unixODBC驱动链接的MySQL数据库客户端库和程序直接链接的MySQL数据库客户端库不一样(因为程序还没有完全改完,有一部分code还会直接调用MySQL数据库客户端库)。

这个坑一定要记住!

一键编译安装gcc

本文原载于我在hellogcc上的文章

今天看到一篇文章,作者通过一个shell脚本和一个Makefile,可以自动下载需要的所有安装包并且自动编译gcc

$ # Download the scripts using wget.
$ mkdir /opt/gcc-4.9.2
$ cd /opt/gcc-4.9.2
$ wget http://projects.joelinoff.com/gcc-4.9.2/bld.sh
$ wget http://projects.joelinoff.com/gcc-4.9.2/Makefile
$ chmod a+x bld.sh
$ make
[output snipped]
$ # The compiler is installed in /opt/gcc-4.9.2/rtf/bin

我试了一下,果然很方便。只要有一台可以联网的机器,就可以了。感兴趣的朋友可以试一试。

P.S.:
(1)编译libiconv时可能会有“'gets' undeclared here“错误,请参考这篇文章
(2)如果机器是64位的,但是缺少32位的库文件。这样在编译gcc时会出现错误:“configure: error: I suspect your system does not have 32-bit developement libraries (libc and headers). If you have them, rerun configure with --enable-multilib. If you do not have them, and want to build a 64-bit-only compiler, rerun configure with --disable-multilib.”。提示需要配置“--disable-multilib”。

ODBC中的三种变量类型

无论是使用ODBC的新手或老兵,看到SQLCHARSOL_C_CHARSQL_CHAR,可能都会有些糊涂。它们之间的区别到底是什么呢?

(1)第一种是ODBC定义的数据类型(像SQLCHAR):SQL开头,后面跟着一系列大写字符,但是没有下划线。这种数据类型定义在sqltypes.h中,比如:

typedef signed short int   SQLSMALLINT;
typedef SQLSMALLINT     SQLRETURN;

#if (ODBCVER >= 0x0300)
typedef void *                  SQLHANDLE; 
......
#endif

这种数据类型可以用来定义变量,ODBC API的变量类型都是这种类型:

#if (ODBCVER >= 0x0300)
    SQLRETURN  SQL_API SQLAllocHandle(SQLSMALLINT HandleType,
                                      SQLHANDLE InputHandle, SQLHANDLE *OutputHandle);
#endif

这样做的好处是ODBC提供了一套自己的变量类型,相当于封装了一层,使用者不用关心底层具体的变量类型实现细节。即使底层的变量类型做了修改,使用者的代码也不用做任何改动。
这种数据类型和C语言数据类型的映射如下:

ODBC 类型 C 类型
SQLCHAR char
SQLSCHAR signed char
SQLINTEGER long int

(2)第二种是C语言的数据类型编码(SQL_C_CHAR)。他们并不是真正的数据类型,而是针对上面提到的的ODBC定义的数据类型的编码,所以不能用来定义变量。他们可以用作ODBC API的参数。这种数据类型定义在sqlext.h中,比如:

#define SQL_C_CHAR    SQL_CHAR             /* CHAR, VARCHAR, DECIMAL, NUMERIC */
#define SQL_C_LONG    SQL_INTEGER          /* INTEGER                      */
#define SQL_C_SHORT   SQL_SMALLINT         /* SMALLINT                     */
#define SQL_C_FLOAT   SQL_REAL             /* REAL                         */
#define SQL_C_DOUBLE  SQL_DOUBLE           /* FLOAT, DOUBLE                */

这种数据类型和ODBC数据类型的映射如下:

整数编码 ODBC 类型
SQL_C_CHAR SQLCHAR
SQL_S_STINYINT SQLSCHAR
SQL_C_SLONG SQLINTEGER

(3)第三种是SQL数据类型编码。同第二种一样,他们也不是真正的数据类型,而是提供SQL数据类型和编程语言数据类型的关联,因为也是数字编码,所以也不能用来定义变量。他们可以用作ODBC API的参数。这种数据类型定义在sqlext.h中,比如:

#define SQL_C_CHAR    SQL_CHAR             /* CHAR, VARCHAR, DECIMAL, NUMERIC */
#define SQL_C_LONG    SQL_INTEGER          /* INTEGER                      */
#define SQL_C_SHORT   SQL_SMALLINT         /* SMALLINT                     */
#define SQL_C_FLOAT   SQL_REAL             /* REAL                         */
#define SQL_C_DOUBLE  SQL_DOUBLE           /* FLOAT, DOUBLE                */

这种数据类型和SQL数据类型的映射如下:

整数编码 SQL类型
SQL_CHAR Char(n)
SQL_VARCHAR Varchar(n)
SQL_SMALLINT Smallint

使用MySQL ODBC一次提交多条SQL语句

MySQL ODBC3.51.18版本开始支持一次提交多个语句(请参考:http://dev.mysql.com/doc/connector-odbc/en/connector-odbc-configuration-connection-parameters.html)。方法是要给odbc.ini的数据源配置值为67108864option。如下图所示:

[DB1]
......
option = 67108864

注意这个option一定要配在odbc.ini的数据源上,而不能配在odbcinst.ini的驱动上。因为MySQLODBC代码只从odbc.ini文件查找option

int ds_lookup(DataSource *ds)
{
    ......
    for (used= 0; used < size; used += sqlwcharlen(entries) + 1,
                             entries += sqlwcharlen(entries) + 1)
      {
        int valsize;
        ds_map_param(ds, entries, &dest, &intdest, &booldest);

        if ((valsize= SQLGetPrivateProfileStringW(ds->name, entries, W_EMPTY,
                                                  val, ODBCDATASOURCE_STRLEN,
                                                  W_ODBC_INI)) < 0)
        {
          rc= 1;
          goto end;
        }
        else if (!valsize)
          /* skip blanks */;
        else if (dest && !*dest)
          ds_set_strnattr(dest, val, valsize);
        else if (intdest)
          *intdest= sqlwchartoul(val, NULL);
        else if (booldest)
          *booldest= sqlwchartoul(val, NULL) > 0;
        else if (!sqlwcharcasecmp(W_OPTION, entries))
          ds_set_options(ds, ds_get_options(ds) | sqlwchartoul(val, NULL));

        RESTORE_MODE();
      }

    ......
}

验证这个配置项是否成功,可以通过wireshark查看建立连接时的抓包:

捕获
可以看到“Multiple Statements”值为1,设置成功。

Powered by WordPress & Theme by Anders Norén