简单的BSON OID生成实现

简单的OID生成测试实现,只是简单的用用,切勿用于生产环境。

/* 应该使用大端序的,这里没有做转换
 * ObjectId是12-byte BSON类型,其结构为:
 *
 *  4-byte 值为Unix时间戳,
 *  3-byte 主机标识,
 *  2-byte 进程ID
 *  3-byte 计数值
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifdef _WIN32
#include <process.h>
#include <Windows.h>
#else
#include <unistd.h>
#include <sys/utsname.h>
#endif

/* 全局的主机标识(这个值可采用主机名散列得到) */
static unsigned char host[4] = {0,0,0,0};
/* 全局计数器(进程一个,要避免访问冲突,当前没有考虑) */
static int counter = 0;
/* 进程ID值 */
static unsigned short pid = 0;

// 简单的将主机名进行散列
void hashhostname(const char* hostname)
{
	host[0] = 0x41;
	host[1] = 0xC6;
	host[2] = 0x4E;
	while(*hostname){
		unsigned char v = *(hostname++);
		host[0] += v >> 2;
		host[1] += v >> 3;
		host[2] += v >> 4;
	}
}

void create_oid()
{
	time_t t = time(NULL);

	unsigned char oid[12];
	*((int*)oid) = (int)t;
	oid[4] = host[0];
	oid[5] = host[1];
	oid[6] = host[2];
	oid[7] = pid;
	oid[8] = pid >> 8;
	oid[9] = counter;
	oid[10] = counter >> 8;
	oid[11] = counter >> 16;
	// 输出
	++counter;
	counter &= 0xffffff;
	int i=0;
	while(i<12){
		printf("%02X",oid[i++]);
	}
	putchar('\n');
}


int main()
{
	// 1、初始化主机标识和进程ID
#ifdef _WIN32
	char buffer[512];
	DWORD buflen = 512;
	GetComputerNameA((LPSTR)buffer,&buflen);
	buffer[511] = '\0';
	puts(buffer);
	hashhostname(buffer);
	pid = (unsigned short)_getpid();
#else
	struct utsname utn;
	if(uname(&utn) < 0 ){
		perror("uname");
		return 0;
	}else{
		printf(" sysname:%s\n nodename:%s\n release:%s\n version:%s\n machine:%s\n \n",
					utn.sysname,
					utn.nodename,
					utn.release,
					utn.version,
					utn.machine);
		hashhostname(utn.nodename);
	}

	pid = (unsigned short)getpid();
#endif
	puts("-----------------------");
	printf(" host=[%hhx,%hhx,%hhx]\n",host[0],host[1],host[2]);
	printf(" pid = %hx\n",pid);
	puts("-----------------------");

	counter = 0xfffffe;
	create_oid();
	create_oid();
	create_oid();
	create_oid();
	return 0;
}
posted @ 2017-06-26 11:36  乌合之众  阅读(915)  评论(0编辑  收藏  举报
clear