예제 #1
0
/*
 * Freeing memory from the small heap
 */
void SH_free(void *mem) {
	//First check if memory was allocated using malloc()
	void * adr = listGetMallocedMemoryAdr(mallocList, mem);
	if (adr != NULL ) {
		free(adr); // Memory was allocated using malloc(), use free instead
		listRemove(mallocList, adr); // Remove address from the list
		return;
	}

	// Memory was not allocated by using malloc, find which small heap it was put into.
	//struct shMapType * shMapEntry = listGetMemoryLocation(SHList, pthread_self());
	// changed to extract allocator's thread_id from mem header rather than by using pthread_self()
	void *ptr = mem - sizeof(SHMemHeaderStruct);
	SHMemHeader header = (SHMemHeader) ptr;
	struct shMapType * shMapEntry = listGetMemoryLocation(SHList, header->thread_id);

	my_mutex_lock(&shMapEntry->mutex);
	unsigned int toFree;  // Pointer to block that needs to be freed
	unsigned int cur, prev;

	toFree = ((unsigned int *) ptr - (shMapEntry->memArea + 1));

	if (toFree < shMapEntry->available) {  // If block, that is being freed is before the first free block

		if (((refToNextBlock(toFree, shMapEntry->memArea) + 1) == shMapEntry->available) && shMapEntry->available < shMapEntry->memAreaSize) // If next free block is immediately after block that is being freed
			shMapEntry->memArea[toFree] += (shMapEntry->memArea[shMapEntry->available] + 1);  // Defragmentation of free space
		else
			shMapEntry->memArea[refToNextBlock(toFree, shMapEntry->memArea)] = shMapEntry->available;

		shMapEntry->available = toFree;
	}

	else {  // If block, that is being freed isn't before the first free block

		prev = cur = shMapEntry->available;

		while (cur < toFree) {
			prev = cur;
			cur = nextBlock(cur, shMapEntry->memArea);
		}

		if ((refToNextBlock(prev, shMapEntry->memArea) + 1) == toFree) { // If previous free block is immediately before block that is being freed

			shMapEntry->memArea[prev] += (shMapEntry->memArea[toFree] + 1);  // Defragmentation of free space

			if (((refToNextBlock(toFree, shMapEntry->memArea) + 1) == cur) && cur < shMapEntry->memAreaSize) // If next free block is immediately after block that is being freed
				shMapEntry->memArea[prev] += (shMapEntry->memArea[cur] + 1);  // Defragmentation of free space
			else
				shMapEntry->memArea[refToNextBlock(toFree, shMapEntry->memArea)] = cur;
		} else {
			shMapEntry->memArea[refToNextBlock(prev, shMapEntry->memArea)] = toFree;
			shMapEntry->memArea[refToNextBlock(toFree, shMapEntry->memArea)] = cur;
		}

	}
	// jonl changed following line as NULL is incorrect, however, it is unclear what it shouldbe
	//log_into_file("freed from", ptr, NULL );
	log_into_file("freed from", ptr, 0 );
	my_mutex_unlock(&shMapEntry->mutex);
}
예제 #2
0
/*
	LockCorrectness:
		Tests correct implementation of the lock

	Parameters:

		parameters:
			A structure of type ThreadParameters_t with parameters

	Return Value:
		

*/
void * LockCorrectness( void *parameters )
{
	
	// ----------------------- Local Variables ------------------

		int i;
		int localN; // On the stack for performance.
		int tmp;
		int j;
		int expectedresult;
		int delaysteps;
		
		ThreadParameters_t *par;


	// ---------------------- Initialization -------------------------

		par = ( ThreadParameters_t * ) parameters;
		localN = gN*30;
		gTestVariable = 0;
		gCounter = 0;

		my_barrier_wait( &gBarrier );


	// ---------------------- Run Tests -------------------------

		for ( i = 0; i < localN; i++ )
		{
			my_mutex_lock( &gMutex );
			tmp = gTestVariable;
			delaysteps = rand() % DELAYNUM;
			for ( j = 0; j < delaysteps; j++ )
			{
				tmp += gZero;
			}
			tmp++;
			gTestVariable = tmp;
			my_mutex_unlock( &gMutex );
		}

	// ---------------------- Barrier wait -------------------------

		my_barrier_wait( &gBarrier );


	// ----------------------- Check for sucess ---------------------

		expectedresult = localN * gP;

		if ( gTestVariable != expectedresult )
		{
			return( NULL );
		}

		return( ( void * ) 1 );

}
예제 #3
0
//轮询超时的实时节点,找到删除
void *pollOverTimeRTNode()
{
	while(1)
	{
		if(my_mutex_lock(&send_lock))
		{
			sleep(OverTimeRTPollTime);  //获取不到锁,继续休眠
			continue;
		}
		RealSendNode *rsn = RealSendList, *preRsn = NULL;
		
		while(rsn)
		{
			if(my_mutex_lock(&(rsn->lock)))
			{
				preRsn = rsn;
				rsn = preRsn->next;
				continue;
			}
			if(rsn->timer <= 0) //需要从列表上删除该节点
			{
				if(rsn == RealSendList) //第一个节点
					RealSendList = rsn->next;
				else
					preRsn->next = rsn->next;
				
				pthread_mutex_unlock(&(rsn->lock));
				//void *status;
				//pthread_join(rsn->tid,&status); //等待创建的线程结束
				RealSendNode *tmp = rsn->next;
				//线程结束后释放该节点信息
				pthread_mutex_destroy(&rsn->lock);
				free(rsn);
				rsn = tmp;
				continue;
			}
			pthread_mutex_unlock(&(rsn->lock));
			preRsn = rsn;
			rsn = preRsn->next;
		}
		pthread_mutex_unlock(&send_lock);

		sleep(OverTimeRTPollTime);
	}
}
예제 #4
0
//轮询列表(查看是否有节点超时未收到数据),线程函数
void *pollDiedNode()
{
	while(1)
	{
		sleep(PollDiedTime);

		uint64 time = getCurrentTimeSeconds();
		//检查第一级液位节点
		LevelFirstNode *lf = LevelFirstList;
		while(lf != NULL)
		{
			if(my_mutex_lock(&(lf->lock)))
			{
				lf = lf->next;
				continue;
			}
			if((lf->active == 1) && ((time - lf->time) >= ActiveDiff))  //节点已经died
			{
				lf->active = 0;
				/**向客户端发送信息通知该节点已经died**/
				sendNodeOnOffBroadInfo(&time,REAL_LEVEL_NODE_OFF,lf->drum);
			}
			pthread_mutex_unlock(&(lf->lock));
			lf = lf->next;
		}
		//检查第一级温度节点
		TempFirstNode *tf = TempFirstList;
		while(tf != NULL)
		{
			if(my_mutex_lock(&(tf->lock)))
			{
				tf = tf->next;
				continue;
			}
			if((tf->active == 1) && ((time - tf->time) >= ActiveDiff))  //节点已经died
			{
				tf->active = 0;
				/**向客户端发送信息通知该节点已经died**/
				sendNodeOnOffBroadInfo(&time,REAL_TEMP_NODE_OFF,tf->drum);
			}
			pthread_mutex_unlock(&(tf->lock));
			tf = tf->next;
		}
	}
}
예제 #5
0
//实时发送列表项必须要客户端发信息才会删除的
int QuitRealSendList(char *username,uint8 drum,enum RealLabel type)
{
	if((username == NULL))
		return -1;
	debug("in quit real send,drum : %d\n",drum);
	//找到节点
	if(my_mutex_lock(&(send_lock)))
		return -1;
	RealSendNode *rsn = RealSendList, *preRsn = NULL;
	while(rsn != NULL)
	{
		if((!memcmp(username,rsn->username,strlen(username))) && (drum == rsn->drum) && (type == rsn->type))
			break;
		preRsn = rsn;
		rsn = preRsn->next;
	}
	 
	if(rsn == NULL) //要么没找到,要么节点列表为空
	{
		pthread_mutex_unlock(&(send_lock));
		return 0;
	}
	else  //有可能是头结点,也有可能是普通节点
	{
		if(preRsn == NULL)   //头结点
			RealSendList = rsn->next;
		else
			preRsn->next = rsn->next;
	}
		
	pthread_mutex_unlock(&(send_lock));
	
	//设置rsn的timer为0,让线程自动free该节点
	if(my_mutex_lock(&(rsn->lock)))
	{
		rsn->timer = 0;  //强制转换,因为已经从列表删除
		return 0;  //表示已经成功
	}
	rsn->timer = 0;
	pthread_mutex_unlock(&(rsn->lock));
	
	return 0;
}
예제 #6
0
//线程函数,实时信息定时发送函数
void *RTSendAction(void *arg)
{
	RealSendNode *rsn = (RealSendNode *)arg;
	//while(1)
	{
		//debug("real time send poll once\n");
		if(my_mutex_lock(&(rsn->lock)))
		{
			debug("can not get lock\n");
	//		continue;
		}
		if(rsn->timer <= 0)
		{
			debug("timer <= 0\n");
			pthread_mutex_unlock(&(rsn->lock));
			sleep(REAL_SEND_PERIOD);
	//		continue;
		}
		RealInfo *ri = getCurrentLTInfo(rsn->drum);  //获取实时信息列表
		if(ri == NULL)
		{
			//debug("ri == NULL");
			pthread_mutex_unlock(&(rsn->lock));
	//		continue;
		}
		uint16 len = 0;
		char *buf = getRealLTInfo(ri,rsn->username,&len);   //获取发送协议
		freeRealInfoList(ri);
		if(buf == NULL)
		{
			debug("buf == NULL");
			pthread_mutex_unlock(&(rsn->lock));
	//		continue;
		}
	
	//	int sendlabel = rsn->timer;
	//	rsn->timer--;
	//	debug("rsn timer :%d\n",rsn->timer);
		pthread_mutex_unlock(&(rsn->lock));
		//因为自始至终都是一个线程操作rsn除了timer以外的东西,所以fd和sendaddr不会改变,这句代码放在外面没有问题
	//实时信息不再定时发送
	//	if(sendlabel == REAL_SEND_TIMER)
			InSendQueue(rsn->fd,&(rsn->sendaddr),buf,len);  //发送
		//debug("real send once ,length: %d  ret : %d\n",len,ret);
		free(buf);
	
	//	sleep(REAL_SEND_PERIOD); //休眠
	}
	
//	pthread_exit("real time send quit");
}
void * thread_routine_2(void * arg)
{
    int tmp;

    my_thread_start();
    my_mutex_lock(&B);
    printf("thread 2 : lock (B)\n");
    my_obj_read(&data2);
    tmp = data2;

    my_mutex_lock(&A);
    printf("thread 2 : lock (A)\n");
    my_obj_write(&data1);
    data1 = tmp-1;

    my_mutex_unlock(&A);
    printf("thread 2 : unlock (A)\n");
    my_mutex_unlock(&B);
    printf("thread 2 : unlock (B)\n");
    my_thread_end();

    return 0;
}
void * thread_routine_2(void * arg)
{
  int tmp;

  my_thread_start();
  my_mutex_lock(&B);
  printf("thread 2 : lock (B)\n");
  
  my_obj_read(&data);
  tmp = data;
  
  my_mutex_unlock(&B);
  printf("thread 2 : unlock (B)\n");
  my_thread_end();

  return 0;
}
void * thread_routine_3(void * arg)
{
  int tmp;

  my_thread_start();

  my_mutex_lock(&C);
  printf("thread 1 : lock (A)\n");
                                                                                                                                                                      
  my_obj_write(&data);
  data = tmp+1;
                                                                                                                                                                   
  my_mutex_unlock(&C);
  printf("thread 1 : unlock (A)\n");

  my_thread_end();

  return 0;
}
예제 #10
0
//找到实时发送列表中的节点,并通过该列表将消息和发送信息加入到发送列表,type为reallabel枚举常量,目前取值范围为ALARM_FISRT,ALARM_SECOND,ALARM_THIRD,NODE_ON,NODE_OFF
int sendNodeOnOffBroadInfo(uint64 *time,enum RealLabel type,uint8 drum)
{
	//如果生成的协议为空
	if((time == NULL) || (drum == (uint8)0))
		return -1;
	
	char resend_type = RESEND_NONE;
	char *buf = NULL;
	uint16 len = 0;
	switch(type)
	{
		case REAL_LEVEL_NODE_ON:
			resend_type = RESEND_LEVEL_NODEON;
			break;
		case REAL_LEVEL_NODE_OFF:
			resend_type = RESEND_LEVEL_NODEOFF;
			break;
		case REAL_TEMP_NODE_ON:
			resend_type = RESEND_TEMP_NODEON;
			break;
		case REAL_TEMP_NODE_OFF:
			resend_type = RESEND_TEMP_NODEOFF;
			break;
		default:
			return -1;
	}
	if(my_mutex_lock(&send_lock))
		return -1;
	RealSendNode *rsn = RealSendList;
	//寻找节点发送
	while(rsn != NULL)
	{
		buf = getNodeOnOffReport(rsn->username,drum,time,type,&len);
		//所有节点都发送,并且要保证发送成功,即保证失败重发
		InTimelyReSendQueue(rsn->fd,&(rsn->sendaddr),buf,len,resend_type,drum);   //发送到定时发送函数,以确保这些重要信息完整的被接收
		free(buf);
		len = 0;
		rsn = rsn->next;
	}
	pthread_mutex_unlock(&send_lock);
	return 0;
}
예제 #11
0
/*
	LockPerformance:
		Tests the performance of a single lock, with no writings or readings.

	Parameters:

		parameters:
			A structure of type ThreadParameters_t with parameters

	Return Value:
		This test always succeeds. It always returns 1.

*/
void * LockPerformance( void *parameters )
{
	
	// ----------------------- Local Variables ------------------

		int i;
		int localN; // On the stack for performance.
		int j;
		ThreadParameters_t *par;


	// ---------------------- Initialization -------------------------

		par = ( ThreadParameters_t * ) parameters;
		localN = gN*15;

		my_barrier_wait( &gBarrier );


	// ---------------------- Run Tests -------------------------

		for ( j = 0; j < 10; j++ )
		{

			my_barrier_wait( &gBarrier );

			for ( i = 0; i < localN; i++ )
			{
				my_mutex_lock( &gMutex );
				my_mutex_unlock( &gMutex );
			}
		}

	// ---------------------- Barrier wait -------------------------

		my_barrier_wait( &gBarrier );

	// ----------------------- Always return success ---------------------

		return( ( void * ) 1 );

}
void * thread_routine_1(void * arg)
{
    int tmp;

    my_thread_start();

    my_mutex_lock(&A);
    printf("thread 1 : lock (A)\n");
    my_obj_read(&data1);
    tmp = data1;

    my_obj_write(&data2);
    data2 = tmp+1;

    my_mutex_unlock(&A);
    printf("thread 1 : unlock (A)\n");

    my_thread_end();

    return 0;
}
예제 #13
0
//发送节点液位报警信息
int sendAlarmBroadInfo(uint64 *time,enum RealLabel type,uint8 drum,uint32 leveldiff)
{
	//如果生成的协议为空
	if((time == NULL) || (drum == (uint8)0) || (leveldiff == (uint32)0))
		return -1;
	
	char resend_type = RESEND_NONE;
	char *buf = NULL;
	uint16 len = 0;
	switch(type)
	{
		//以下信息都是广播信息
		case REAL_ALARM_FISRT:
		case REAL_ALARM_SECOND:
		case REAL_ALARM_THIRD:
			resend_type = RESEND_ALARM;
			break;
		default:
			return -1;
	}

	if(my_mutex_lock(&send_lock))
		return -1;
	RealSendNode *rsn = RealSendList;
	//寻找节点发送
	while(rsn != NULL)
	{
		buf = getAlarmInfo(rsn->username,drum,time,type,leveldiff,&len);
		//所有节点都发送,并且要保证发送成功,即保证失败重发
		InTimelyReSendQueue(rsn->fd,&(rsn->sendaddr),buf,len,resend_type,drum);   //发送到定时发送函数,以确保这些重要信息完整的被接收
		free(buf);
		len = 0;
		rsn = rsn->next;
	}
	pthread_mutex_unlock(&send_lock);
	return 0;
}
예제 #14
0
/*
 * Allocator of memory, allocates into the specified small heap
 */
void *SH_alloc_at_base(unsigned int data_size, struct shMapType * shMapEntry) {
	if (data_size == 0) {  // Return NULL pointer after attempt to allocate 0-length memory
		return NULL ;
	}

	my_mutex_lock(&shMapEntry->mutex);

	// changed to deal with sh memory header containing the allocator's thread_id
	unsigned int size = data_size + sizeof(SHMemHeaderStruct);
	unsigned int num = size / sizeof(unsigned int);
	if (size % sizeof(unsigned int) > 0)
		num++;
	unsigned int cur, prev;  					// Index of the current block, previous block
	unsigned int isFirstFreeBeingAllocated = 1; // Whether the first free block is being allocated

	prev = cur = shMapEntry->available;

	// Check if we have enough free space for allocation
	test:

	if (shMapEntry->available == shMapEntry->memAreaSize) {  // If we are on the end of the memory
		return NULL ;
	}

	if (blockSize(cur, shMapEntry->memArea) < num) {  // If the size of free block is lower than requested
		isFirstFreeBeingAllocated = 0;
		prev = cur;

		if (nextBlock(cur, shMapEntry->memArea) == shMapEntry->memAreaSize) {  // If not enough memory
			return NULL ;
		} else
			cur = nextBlock(cur, shMapEntry->memArea);
		goto test;
	}

	if (blockSize(cur, shMapEntry->memArea) == num) {  // If the size of free block is equal to requested

		if (isFirstFreeBeingAllocated)
			shMapEntry->available = nextBlock(cur, shMapEntry->memArea);
		else
			shMapEntry->memArea[refToNextBlock(prev, shMapEntry->memArea)] = nextBlock(cur, shMapEntry->memArea);
	}

	else {  // If the size of free block is greater than requested

		if (isFirstFreeBeingAllocated) {
			if ((blockSize(cur, shMapEntry->memArea) - num) == 1)  // If there is only 1 free item left from this (previously) free block
				shMapEntry->available = nextBlock(cur, shMapEntry->memArea);
			else
				shMapEntry->available = cur + num + 1;
		} else {
			if ((blockSize(cur, shMapEntry->memArea) - num) == 1)  // If there is only 1 free item left from this (previously) free block
				shMapEntry->memArea[refToNextBlock(prev, shMapEntry->memArea)] = nextBlock(cur, shMapEntry->memArea);
			else
				shMapEntry->memArea[refToNextBlock(prev, shMapEntry->memArea)] = cur + num + 1;
		}

		if ((blockSize(cur, shMapEntry->memArea) - num) == 1)  // If there is only 1 free item left from this (previously) free block
			shMapEntry->memArea[cur] = num + 1;
		else {
			shMapEntry->memArea[cur + num + 1] = blockSize(cur, shMapEntry->memArea) - num - 1;
			shMapEntry->memArea[cur] = num;
		}
	}
	log_into_file("allocated at", (void *) &(shMapEntry->memArea[cur + 1]), size);  // Log into a file, if required.
	// return (void *) &(shMapEntry->memArea[cur + 1]);
	// change to deal with mem header recording the allocator's thread_id
	char *new_base = (char *) &(shMapEntry->memArea[cur + 1]);
	SHMemHeader header = (SHMemHeader) new_base;
	header->thread_id = shMapEntry->thread_id;
	my_mutex_unlock(&shMapEntry->mutex);
	return (void *) ( new_base + sizeof(SHMemHeaderStruct));
}
예제 #15
0
//加入实时发送列表
int InRealSendList(char *username,uint8 drum,int fd,struct sockaddr_in *addr, enum RealLabel type)
{
	if((username == NULL) || (fd == 0) || (addr == NULL) || (type == REAL_NONE))
		return -1;
	
	//先判断该节点是否已经存在于列表中
	if(my_mutex_lock(&(send_lock)))
		return -1;
	RealSendNode *node = RealSendList, *preNode = NULL;
	while(node != NULL)
	{
		if(!memcmp(node->username,username,strlen(username))) //已经存在
		{
			//检查网络地址是否相同,也相同的话则不再建立新节点,不同则删除当前节点并建立新节点
			if((node->sendaddr.sin_addr.s_addr == addr->sin_addr.s_addr) && (node->sendaddr.sin_port == addr->sin_port))
			{	debug("duplicate node in real send list\n");
				pthread_mutex_unlock(&(send_lock));
				RTSendAction(node);
				return 0;
			}
			else
			{
				//删除原来节点,将该节点从列表上删除并且设置原来节点的timer值,线程会自动free该节点
				if(node == RealSendList) //要删除的是头结点
					RealSendList = node->next;
				else //普通节点
					preNode->next = node->next;
			}
			break;
		}
		
		preNode = node;
		node = preNode->next;
	}
	pthread_mutex_unlock(&(send_lock));
	//设置timer标志,使线程删除该节点,放在外面避免了锁嵌套
	if(node != NULL)
	{
		if(my_mutex_lock(&(node->lock)))
		{
			node->timer = 0;   //即使未获取到锁也要强制转换,因为该节点已经删除
			return -1;
		}
		node->timer = 0;
		pthread_mutex_unlock(&(node->lock));
	}
	
	//新建节点(节点未找到或者刚刚被删除)
	RealSendNode *rsn = (RealSendNode *)malloc(sizeof(RealSendNode));
	memset(rsn,0,sizeof(RealSendNode));
	memcpy(rsn->username,username,strlen(username));  //用户名赋值
	rsn->drum = drum;
	rsn->fd = fd;				//套接字文件
	memcpy(&(rsn->sendaddr),addr,sizeof(struct sockaddr_in));  //用户地址
	rsn->type = type;				//请求类型
	rsn->timer = REAL_SEND_TIMER;
	pthread_mutex_init(&(rsn->lock),NULL);
	
	//debug("before add in real send list\n");
	//加入列表
	if(my_mutex_lock(&(send_lock)))
	{
		pthread_mutex_destroy(&(rsn->lock));
		free(rsn);
		return -1;
	}
	if(RealSendList == NULL)  //列表起始为空
		RealSendList = rsn;
	else   //添加作为头结点
	{
		rsn->next = RealSendList;
		RealSendList = rsn;
	}
	pthread_mutex_unlock(&(send_lock));
	
	//给一个线程执行该节点任务(不需要了)
//	pthread_t tid;
//	pthread_create(&tid,NULL,RTSendAction,(void *)rsn);   //创建线程循环执行重发命令
//	rsn->tid = tid;
	rsn->tid = 0;
	//pthread_detach(tid);		//不要设置线程分离,因为要等待该线程完成

	debug("after add in real time list\n");
	return 0;
}
예제 #16
0
//收到新数据信息,数据取地址,type只有两种first类型
int addNewLTInfo(enum LTLabel type,void *info,uint8 drum)
{
	if((info == NULL) || (drum == (uint8)0) || (drum >= NumofDrums))
		return -1;
	
	switch(type)
	{
		case L_FIRST: //收到液位信息
		{	LevelFirstNode *lf = LevelFirstList;
			int step = 0;  //用于直接到达二级、三级节点结构
			while(lf != NULL)
			{
				if(lf->drum == drum)  //找到添加的节点,这些节点都不会被删除,并且drum不会改变,所以,锁lock可以不用包含这句话
				{	
					if(my_mutex_lock(&lf->lock)) //这里就需要加锁,未获取到锁
						return -1;
					uint64 curtime = getCurrentTimeSeconds();//获取当前时间
					uint16 level = *(uint16 *)info;  //获取液位信息
					LTInfo *ltinfo = NULL;
					int alarm = 0;
					uint16 first_leveldiff = 0;
					if(lf->time != (uint64)0)  //如果不为系统第一次接收数据
					{
						//判断是否需要报警
						if((former_first_level[drum - 1] > level) && ((first_leveldiff=(former_first_level[drum - 1] - level)) >= LevelFirstDiff))
						{
							//debug("first level alarm\n");
							//报警
							sendAlarmBroadInfo(&curtime,REAL_ALARM_FISRT,drum,first_leveldiff);
							alarm = 1;
						}
						
						//不是系统第一次接受数据的话需要将原来的值存入数据库中
						ltinfo = (LTInfo *)malloc(sizeof(LTInfo));
						memset(ltinfo,0,sizeof(LTInfo));
						ltinfo->time = lf->time;
						ltinfo->drum = lf->drum;
						ltinfo->lt.level = lf->lt.level;
						if(addLTInfo(ltinfo,L_FIRST))
						{
							debug("add ltinfo first level error\n");
							free(ltinfo);
							pthread_mutex_unlock(&lf->lock);
							return -1;
						}
					}
					former_first_level[drum - 1] = level;
					//开始修改第一级节点信息
					lf->time = curtime;
					lf->lt.level = level;
					if(lf->active == 0)
					{
						lf->active = 1;
						/******向客户端发送信息通知节点成功接入协议,轮询实时发送列表,然后发送*******/
						//debug("******node add in success*********\n");
						sendNodeOnOffBroadInfo(&curtime,REAL_LEVEL_NODE_ON,drum);
					}
					
					pthread_mutex_unlock(&(lf->lock));
					lf = NULL;  //以防出错
					
					/**接着找到第二级节点并修改信息**/
					LevelSecondNode *ls = LevelSecondList;
					for(int i = 0; i < step; i++)  //根据初始化时的结构可知,各级的桶号是一一对应的
						ls = ls->next;
					if((ls == NULL) || (ls->drum != drum))
					{
						debug("can not find second level by first\n");
						free(ltinfo);
						return -1;
					}
					//找到第二级节点,比较时间,添加节点信息
					if(my_mutex_lock(&(ls->lock)))
					{
						free(ltinfo);
						return -1;
					}
					if((curtime / FSTTOSEC) == (ls->time / FSTTOSEC))  //在同一个时间段内,time和ls->time除以每小时的秒数值肯定相同
					{
						//时间time不能修改
						ls->lt.sum_level += level;
						ls->num++;
						pthread_mutex_unlock(&(ls->lock));
					}
					else				//不在同一个时间段内
					{
						if(ls->num != 0)   //非第一次存入值,第一次的时候num也为0
						{
							uint16 second_leveldiff = 0;
							//判断是否需要报警
							if((!alarm) && (former_second_level[drum-1] > level) && ((second_leveldiff=(former_second_level[drum-1] - level)) >= LevelSecondDiff))
							{
								debug("second level alarm\n");
								//报警
								sendAlarmBroadInfo(&curtime,REAL_ALARM_SECOND,drum,second_leveldiff);
								alarm = 1;
							}
							
							//先将原时间段存入数据库中
							ltinfo->time = ls->time;					//drum前面已经赋值过了
							ltinfo->lt.level = (uint16)((ls->lt.sum_level) / (ls->num));    //存入数据库的是平均值
							ltinfo->num = ls->num;
							if(addLTInfo(ltinfo,L_SECOND))
							{
								pthread_mutex_unlock(&(ls->lock));
								debug("add ltinfo error");
								free(ltinfo);
								return -1;
							}
						}
						former_second_level[drum-1] = level;
						//然后给该二级节点赋新值
						uint32 sum_level = ls->lt.sum_level;
						uint16 num = ls->num;
						ls->time = curtime;
						ls->lt.sum_level = level;
						ls->num = 1;
						pthread_mutex_unlock(&(ls->lock));
						ls = NULL;
						
						/** 当二级节点被存入数据库后,同时将该节点加入第三级节点中 **/
						LevelThirdNode *lt = LevelThirdList;
						for(int i = 0; i < step; i++)  //找到三级节点
							lt = lt->next;
						if((lt == NULL) || (lt->drum != drum))
						{
							debug("can not find third level by second\n");
							free(ltinfo);
							return -1;
						}
						if(my_mutex_lock(&(lt->lock)))
						{
							free(ltinfo);
							return -1;
						}
						if((curtime / SECTOTHD) == (lt->time / SECTOTHD)) //与第三级节点在同一个设定的时间段内
						{
							lt->lt.sum_level += sum_level;
							lt->num += num;
							pthread_mutex_unlock(&(lt->lock));
						}
						else    //不在一个时间段内
						{
							if(lt->num != 0)
							{
								uint16 third_leveldiff = 0;
								//判断是否需要报警
								if((!alarm) && (former_third_level[drum-1] > level) && ((third_leveldiff=(former_third_level[drum-1] - level)) >= LevelThirdDiff))
								{//报警
									debug("third level alarm\n");
									sendAlarmBroadInfo(&curtime,REAL_ALARM_THIRD,drum,third_leveldiff);
								}
								ltinfo->time = lt->time;					//drum前面已经赋值过了
								ltinfo->lt.level = (uint16)((lt->lt.sum_level) / (lt->num));    //存入数据库的是平均值
								ltinfo->num = lt->num;
								if(addLTInfo(ltinfo,L_THIRD))
								{
									pthread_mutex_unlock(&(lt->lock));
									debug("add ltinfo error");
									free(ltinfo);
									return -1;
								}
							}
							former_third_level[drum-1] = level;
							//给三级节点赋新值
							lt->time = curtime;
							lt->lt.sum_level = sum_level;
							lt->num = num;
							pthread_mutex_unlock(&(lt->lock));
						}
					}
					if(ltinfo)
						free(ltinfo);
					return 0;
				}
				lf = lf->next;
				step++;
			}
		}
			break;
		case T_FIRST: //收到温度信息
		{//	debug("in temp first add\n");
			TempFirstNode *tf = TempFirstList;
			int step = 0;  //用于直接到达二级、三级节点结构
			while(tf != NULL)
			{
				if(tf->drum == drum)  //找到添加的节点,这些节点都不会被删除,并且drum不会改变,所以,锁lock可以不用包含这句话
				{
					if(my_mutex_lock(&(tf->lock)))
						return -1;
					uint64 curtime = getCurrentTimeSeconds(); //获取当前时间
					float temp = *(float *)info;  //获取温度信息
					LTInfo *ltinfo = NULL;
					if(tf->time != (uint64)0)  //如果不为系统第一次接收数据
					{
						//温度不需要报警,将原来的值存入数据库中
						ltinfo = (LTInfo *)malloc(sizeof(LTInfo));
						memset(ltinfo,0,sizeof(LTInfo));
						ltinfo->time = tf->time;
						ltinfo->drum = tf->drum;
						ltinfo->lt.temp = tf->lt.temp;
						if(addLTInfo(ltinfo,T_FIRST))
						{
							debug("add ltinfo error");
							free(ltinfo);
							return -1;
						}
					}
					//开始修改第一级节点信息
					tf->time = curtime;
					tf->lt.temp = temp;
					if(tf->active == 0)
					{
						tf->active = 1;
						/******向客户端发送信息通知节点成功接入协议,轮询实时发送列表,然后发送*******/
						sendNodeOnOffBroadInfo(&curtime,REAL_TEMP_NODE_ON,drum);
					}
					pthread_mutex_unlock(&(tf->lock));
					tf = NULL;  //以防出错
					
					/**接着找到第二级节点并修改信息**/
					TempSecondNode *ts = TempSecondList;
					for(int i = 0; i < step; i++)  //根据初始化时的结构可知,各级的桶号是一一对应的
						ts = ts->next;
					if((ts == NULL) || (ts->drum != drum))
					{
						debug("can not find second level by first\n");
						free(ltinfo);
						return -1;
					}
					//找到第二级节点,比较时间,添加节点信息
					if(my_mutex_lock(&(ts->lock)))
					{
						free(ltinfo);
						return -1;
					}
					if((curtime / FSTTOSEC) ==(ts->time / FSTTOSEC))  //在同一个时间段内,time一定比ts->time大,第一次的话ts->time 为0,差值一定大于FSTTOSEC,所以这几句代码不执行
					{
						//时间time不能修改
						ts->lt.sum_temp += temp;
						ts->num++;
						pthread_mutex_unlock(&(ts->lock));
					}
					else				//不在同一个时间段内
					{
						if(ts->num != 0)
						{
							//先将原时间段存入数据库中
							ltinfo->time = ts->time;					//drum前面已经赋值过了
							ltinfo->lt.temp = (ts->lt.sum_temp) / (ts->num);    //存入数据库的是平均值
							ltinfo->num = ts->num;
							if(addLTInfo(ltinfo,T_SECOND))
							{
								pthread_mutex_unlock(&(ts->lock));
								debug("add ltinfo error");
								free(ltinfo);
								return -1;
							}
						}
						//然后给该二级节点赋新值
						float sum_temp = ts->lt.sum_temp;
						uint16 num = ts->num;
						ts->time = curtime;
						ts->lt.sum_temp = temp;
						ts->num = 1;
						pthread_mutex_unlock(&(ts->lock));
						ts = NULL;
						
						/** 当二级节点被存入数据库后,同时将该节点加入第三级节点中 **/
						TempThirdNode *tt = TempThirdList;
						for(int i = 0; i < step; i++)  //找到三级节点
							tt = tt->next;
						if((tt == NULL) || (tt->drum != drum))
						{
							debug("can not find third level by second\n");
							free(ltinfo);
							return -1;
						}
						if(my_mutex_lock(&(tt->lock)))
						{
							free(ltinfo);
							return -1;
						}
						if((curtime / SECTOTHD) ==(tt->time / SECTOTHD)) //与第三级节点在同一个设定的时间段内
						{
							tt->lt.sum_temp += sum_temp;
							tt->num += num;
							pthread_mutex_unlock(&(tt->lock));
						}
						else    //不在一个时间段内
						{
							if(tt->num != 0)
							{
								ltinfo->time = tt->time;					//drum前面已经赋值过了
								ltinfo->lt.temp = (tt->lt.sum_temp) / (tt->num);    //存入数据库的是平均值
								ltinfo->num = tt->num;
								if(addLTInfo(ltinfo,T_THIRD))
								{
									pthread_mutex_unlock(&(tt->lock));
									debug("add ltinfo error");
									free(ltinfo);
									return -1;
								}
							}
							//给三级节点赋新值
							tt->time = curtime;
							tt->lt.sum_temp = sum_temp;
							tt->num = num;
							pthread_mutex_unlock(&(tt->lock));
						}
					}
					if(ltinfo)  //不为空则释放
						free(ltinfo);
					return 0;
				}
				tf = tf->next;
				step++;
			}
		}
			break;
		default:
			return -1;
	}
	
	return -1;
}
예제 #17
0
//查询实时数据信息,当drum为0时,表示全部查询,查询结果仅为first 第一级内容,其他级内容不为实时内容
RealInfo *getCurrentLTInfo(uint8 drum)
{
	//debug("in get current lt info\n");
	LevelFirstNode *lf = LevelFirstList;
	TempFirstNode *tf = TempFirstList;
	RealInfo *ri = NULL;
	RealInfo *node = NULL;
	
	//debug("drum = %d\n",drum);
	if(drum == 0) 
	{//全部查询

		while((lf != NULL) && (tf != NULL))
		{
			if(my_mutex_lock(&(lf->lock)))
			{
				lf = lf->next;
				tf = tf->next;
				continue;
			}
			if(my_mutex_lock(&(tf->lock)))
			{
				pthread_mutex_unlock(&(lf->lock));
				lf = lf->next;
				tf = tf->next;
				continue;
			}
			//debug("lf->drum : %d, lf->active : %d; tf->drum : %d,tf->active : %d\n",lf->drum,lf->active,tf->drum,tf->active);
			if(!((lf->active) || (tf->active)))	//至少保证单个桶上有一个节点在工作,否则不作为查询结果
			{
				pthread_mutex_unlock(&(lf->lock));   //锁嵌套是非常危险的行为,但是所有代码中只有此处用到了锁嵌套,所以安全
				pthread_mutex_unlock(&(tf->lock));
				lf = lf->next;
				tf = tf->next;
				continue;
			}
			if(ri != NULL)
			{
				node->next = (RealInfo *)malloc(sizeof(RealInfo));
				node = node->next;
				memset(node,0,sizeof(RealInfo));
			}
			else
			{
				ri = (RealInfo *)malloc(sizeof(RealInfo));
				memset(ri,0,sizeof(RealInfo));
				node = ri;
			}
			node->drum = lf->drum;
			node->level = lf->lt.level;
			if(lf->active == 0)
				node->level = 0;
			node->temp = tf->lt.temp;
			if(tf->active == 0)
				node->temp == .0;
			
			pthread_mutex_unlock(&(tf->lock));
			pthread_mutex_unlock(&(lf->lock));
			//lf与tf对应的
			lf = lf->next;
			tf = tf->next;
		}

		//debug("geted real info\n");
		return ri;
	}
	else  //单个查询
	{
		while((lf != NULL) && (tf != NULL))
		{
			if(my_mutex_lock(&(lf->lock)))
			{
				lf = lf->next;
				tf = tf->next;
				continue;
			}
			if(my_mutex_lock(&(tf->lock)))
			{
				pthread_mutex_unlock(&(lf->lock));
				lf = lf->next;
				tf = tf->next;
				continue;
			}
			if(!((lf->active) || (tf->active)))
			{
				pthread_mutex_unlock(&(tf->lock));
				pthread_mutex_unlock(&(lf->lock));
				lf = lf->next;
				tf = tf->next;
				continue;
			}
			if((lf->drum == drum) && (tf->drum == drum))
			{
				ri = (RealInfo *)malloc(sizeof(RealInfo));
				memset(ri,0,sizeof(RealInfo));
				ri->drum = drum;
				ri->level = lf->lt.level;
				if(lf->active == 0)
					ri->level = 0;
				ri->temp = tf->lt.temp;
				if(tf->active == 0)
					ri->temp == .0;

				pthread_mutex_unlock(&(tf->lock));
				pthread_mutex_unlock(&(lf->lock));
				break;
			}
			
			pthread_mutex_unlock(&(tf->lock));
			pthread_mutex_unlock(&(lf->lock));
			lf = lf->next;
			tf = tf->next;
		}
		//debug("get single realinfo\n");
		return ri;
	}
}