sds-1

sds结构-1

数据结构

这里比较有意思的是GNU C的零长度数组,sizeof(char buf[0]) == 0, 关于这篇内容的C语言技巧改日写一篇文章阐述

struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len; /* used */
    uint16_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
    uint32_t len; /* used */
    uint32_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
    uint64_t len; /* used */
    uint64_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};   

len:字符串长度
alloc:可用容量
flags:数据类型
buf:字符数据

可以看到,内容相同的数据结构,因为类型的原因按字长定义了四种。 redis存储的时候选最小的可用的结构去描述字符串,在避免内存消耗方面做到了极致。

宏解析

#define SDS_TYPE_8  1
#define SDS_TYPE_16 2
#define SDS_TYPE_32 3
#define SDS_TYPE_64 4
#define SDS_TYPE_MASK 7
#define SDS_TYPE_BITS 3
#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)));
#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))
#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)   

flags值最大为4,占3位,所以SDS_TYPE_BITS为3,SDS_TYPE_MASK为7。
SDS_HDR就是获得一个类型的基地址,同时做了强制类型转换,这里所谓的基地址就是结构体的地址。
SDS_HDR_VAR就是定义了一个具体类型的指针。
可以看到redis作者通过宏来动态管理字符串的类型。这些trick玩的比较好,有可能是我玩单片机的时候接触不到这么高级的写法。

函数解析

因为传入的sds都是真正存储的位置,而函数中都会先获取到具体类型才执行相应逻辑。
unsigned char flags = s[-1];
因为声明结构体时已经取消了优化字节对齐,所以这些结构体都是程序都是连续存储的。
上述操作就是拿到了结构体的flags成员,这里的trick就是[]的玩法,其实就是base_addr+offset

sdslen
typedef char *sds;

static inline size_t sdslen(const sds s) {
    unsigned char flags = s[-1];
    switch(flags&SDS_TYPE_MASK) {
        case SDS_TYPE_5:
            return SDS_TYPE_5_LEN(flags);
        case SDS_TYPE_8:
            return SDS_HDR(8,s)->len;
        case SDS_TYPE_16:
            return SDS_HDR(16,s)->len;
        case SDS_TYPE_32:
            return SDS_HDR(32,s)->len;
        case SDS_TYPE_64:
            return SDS_HDR(64,s)->len;
    }
    return 0;
}
//就是获取到真正类型后直接取出对应的成员

static inline size_t sdsavail(const sds s);
static inline void sdssetlen(sds s, size_t newlen);
static inline void sdsinclen(sds s, size_t inc);
static inline size_t sdsalloc(const sds s);
static inline void sdssetalloc(sds s, size_t newlen);
//上述几个函数都是对结构体成员的获取和更新    

//其实就是在算法前多了获取类型的操作

总结

觉得自己学的很浅,很多都没有接触过。redis作者这么巧妙的使用宏和各种自己想不到的知识点去实现,很有学习借鉴意义。你和大神的差别就在思想。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SDS(SQL Data Security)是一款专门用于SQL数据库文件加密的保密软件。通过加密和访问控制技术,可控制SQL数据库文件无法拷贝,禁止导出,备份加密,远程销毁,脱离环境无法打开等等。 SDS分为管理程序和控制程序,需要在安装SQL Server数据库的机器上安装控制程序和管理程序,可在局域网内安装管理程序对SDS软件进行远程操控,安装后,所有数据库文件将处于加密状态,即使将文件拷贝出去也无法使用。同时,通过SQL企业管理器备份出来的数据也是加密的,离开本机环境将无法使用,SDS可禁止SQL组件导出数据。 SDS与数据库应用程序及数据库大小无关,后台实时监控数据的写入和读取,不会影响应用程序正常调用数据。 SDS的特点如下: 1.安装,维护简单。一键式安装,配套安装使用教程,专业的售后维护团队。 2.后台运行,实时监控数据库的读写。 3.数据库数据拷贝离开本机环境无法使用。本机环境内则不受影响。 4.与应用程序无关,不影响应用程序使用。ERP、PDM、等管理系统可以正常调用数据库文件,和正常操作一样。 5.与数据库大小无关。 6.通过设置,可本地或管理端临时禁用数据库。黑客来袭或者紧急情况可以通过本软件提供的禁用数据库功能使数据库文件无法打开,即使在本机环境依然无法正常打开使用,之后可恢复正常状态。 7.可设定云端验证。当服务器被盗时,可以是服务器电脑在本公司环境外部无法正常开机,卸载硬盘更换电脑依然无法正常开机,即数据库文件不会被外人获取。 SDS目前支持SQL2000、SQL2005、SQL2008、SQL2012。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值