Beispiel #1
0
static void send_ipi_msg(const struct cpumask *mask, unsigned int action)
{
	unsigned int msg;
	unsigned long flags = 0;

#define SEND_MSG(CPU)	do {					\
	if(cpu_isset(CPU,*mask)) {				\
		msg = action | get_smp_mbox##CPU();		\
		set_smp_mbox##CPU(msg);				\
	} } while(0)

	spin_lock_irqsave(&smp_lock,flags);

	SEND_MSG(0);
	SEND_MSG(1);
	SEND_MSG(2);
	SEND_MSG(3);

	spin_unlock_irqrestore(&smp_lock,flags);
}
void *ptfsal_closeHandle_listener_thread(void *args)
{
  int rc;
  struct msg_t msg;
  int msg_bytes;
  int close_rc;
  int i;
  struct CommonMsgHdr *msgHdr;
  int handleIdxFound;

  SetNameFunction("PT FSAL CloseOnOpen Handler");

  rc = ptfsal_closeHandle_attach_to_queues();
  if (rc == -1) {
    exit (1);
  }

  while (1) {
    msg_bytes = RCV_MSG_WAIT_BLOCK(g_closeHandle_req_msgq,
                                   &msg,
                                   sizeof(struct CommonMsgHdr),
                                   0);
    if (msg_bytes != -1) {
      close_rc = -1;
      FSI_TRACE(FSI_NOTICE, "Finding oldest handles");
      /* TBD: we need to address a design if we have more than one
              close thread or NFS4 support (that can issue close itself)
              in order to ensure proper locking to the handle table.
              Currently, one close thread model will work since we don't
              shuffle handle around and there is only one place to
              actually close the handle (which is here) in the code */

      handleIdxFound = CCL_FIND_OLDEST_HANDLE();
      if (handleIdxFound != -1) {
        close_rc = ptfsal_implicit_close_for_nfs(handleIdxFound,
                                                 CCL_CLOSE_STYLE_NORMAL);
      }
      /* Send the response back */
      msgHdr = (struct CommonMsgHdr *) &msg.mtext[0];
      msgHdr->transactionRc = close_rc;
      msg_bytes = SEND_MSG(g_closeHandle_rsp_msgq,
                           &msg,
                           sizeof(struct CommonMsgHdr));
    }
  }
}
Beispiel #3
0
/**
 * Run signal test
 */
int msg_testRun(void)
{
	MsgPort test_portMain;
	TestMsg msg0;
	TestMsg msg1;
	TestMsg msg2;
	TestMsg msg3;
	TestMsg msg4;
	TestMsg msg5;
	TestMsg *reply;

	// Allocate and start the test process
    struct Process *recv0 = RECV_INIT_PROC(0);
    struct Process *recv1 = RECV_INIT_PROC(1);
    struct Process *recv2 = RECV_INIT_PROC(2);
    struct Process *recv3 = RECV_INIT_PROC(3);
    struct Process *recv4 = RECV_INIT_PROC(4);
    struct Process *recv5 = RECV_INIT_PROC(5);

	kprintf("Run Message test..\n");

	// Init port and message
    RECV_INIT_MSG(Main, proc_current(), SIG_SINGLE);
    RECV_INIT_MSG(0, recv0, SIG_USER0);
    RECV_INIT_MSG(1, recv1, SIG_USER1);
    RECV_INIT_MSG(2, recv2, SIG_USER2);
    RECV_INIT_MSG(3, recv3, SIG_USER3);
    RECV_INIT_MSG(4, recv4, SIG_SYSTEM5);
    RECV_INIT_MSG(5, recv5, SIG_SYSTEM6);

	// Fill-in first message and send it out.
	fill_msg(&msg0, INC_PROC_T0, DELAY_PROC_T0, 0);
	fill_msg(&msg1, INC_PROC_T1, DELAY_PROC_T1, 0);
	fill_msg(&msg2, INC_PROC_T2, DELAY_PROC_T2, 0);
	fill_msg(&msg3, INC_PROC_T3, DELAY_PROC_T3, 0);
	fill_msg(&msg4, INC_PROC_T4, DELAY_PROC_T4, 0);
	fill_msg(&msg5, INC_PROC_T5, DELAY_PROC_T5, 0);


	// Send and wait the message
	for (int i = 0; i < 23; ++i)
    {
		process_num = 0;
		SEND_MSG(0);
		SEND_MSG(1);
		SEND_MSG(2);
		SEND_MSG(3);
		SEND_MSG(4);
		SEND_MSG(5);
		while(1)
		{
			sigmask_t sigs = sig_waitTimeout(SIG_SINGLE, ms_to_ticks(TEST_TIME_OUT_MS));
			if (sigs & SIG_SINGLE)
			{
				// Wait for a reply...
				while ((reply = (TestMsg *)msg_get(&test_portMain)))
				{
					count += reply->result;
					kprintf("Main recv[%d] count[%d]\n", reply->result, count);
				}
			}
			
			if (process_num == 6)
				break;

			if (sigs & SIG_TIMEOUT)
			{
				kputs("Main: sig timeout\n");
				goto error;
			}
		}
    }

	if(count == MAX_GLOBAL_COUNT)
	{
		kprintf("Message test finished..ok!\n");
		return 0;
	}
	
error:
	kprintf("Message test finished..fail!\n");
	return -1;
}
Beispiel #4
0
int tuple_process(tuple_t tuple, unsigned char *pc,
		  int isNew, Register *reg)
{
  for (; ; pc = advance(pc)) {
  eval_loop: /* for jump instructions */
    switch (0xf0 & *(const unsigned char*)pc) {

    case 0x00: // some '8-bit' instruction
      switch (0x0f & *(const unsigned char*)pc) {

      case 0x00: // RETURN
#ifdef DEBUG_INSTRS
	printf("RETURN\n");
#endif
	return RET_RET;
	break;

      case 0x01: // NEXT
#ifdef DEBUG_INSTRS
	printf("NEXT\n");
#endif
	return RET_NEXT;
	break;

      case 0x02: // ELSE
	fprintf(stderr, "ELSE NOT IMPLEMENTED YET!\n");
	assert(0);
	break;

      case 0x08: // SEND
      case 0x09: // SEND
      case 0x0a: // SEND
      case 0x0b: // SEND
	{
	const unsigned char *old_pc = pc+3;
	Register send_reg = reg[SEND_MSG(pc)];
	Register send_rt = reg[SEND_RT(pc)];

#ifdef DEBUG_INSTRS
	printf("SEND\n");
#endif

	tuple_send((tuple_t)MELD_CONVERT_REG_TO_PTR(send_reg),
		   MELD_CONVERT_REG_TO_PTR(send_rt),
		   MELD_INT(eval(SEND_DELAY(pc), &tuple, &old_pc, reg)), isNew);
	break;
	}

      default:
	fprintf(stderr, "INVALID INSTRUCTION %u", *pc);
	assert(0);
	break;
      }
      break;

    case 0x20: // CALL
      {
      Register *dst = &reg[CALL_DST(pc)];
      Register args[CALL_ARGS(pc)];

      assert(CALL_ARGS(pc) <= 5);

#ifdef DEBUG_INSTRS
      printf("CALL %d (%d)\n", CALL_ID(pc), CALL_ARGS(pc));
#endif
        
      int i;
      const unsigned char *old_pc = pc+2;
      for (i = 0; i < CALL_ARGS(pc); i++) {
	unsigned char value = CALL_VAL(old_pc);
	old_pc++;
	args[i] = MELD_CONVERT_PTR_TO_REG(eval(value, &tuple, &old_pc, reg));
      }

      switch (CALL_ARGS(pc)) {
      default:
	break;
      case 0:
	*dst = CALL_FUNC(pc)();
	break;
      case 1:
	*dst = CALL_FUNC(pc)(args[0]);
	break;
      case 2:
	*dst = CALL_FUNC(pc)(args[0], args[1]);
	break;
      case 3:
	*dst = CALL_FUNC(pc)(args[0], args[1], args[2]);
	break;
      case 4:
	*dst = CALL_FUNC(pc)(args[0], args[1], args[2], args[3]);
	break;
      case 5:
	*dst = CALL_FUNC(pc)(args[0], args[1], args[2], args[3], args[4]);
	break;
      }
      break;
      }

    case 0x30: // MOVE
      {
      const unsigned char *old_pc = pc+2;

#ifdef DEBUG_INSTRS
      {
	char src = MOVE_SRC(pc);
	char dst = MOVE_DST(pc);

        printf("MOVE ");
        if(VAL_IS_TUPLE(src))
          printf("tuple");
        else if(VAL_IS_REG(src))
          printf("reg %d", VAL_REG(src));
        else if(VAL_IS_HOST(src))
          printf("host");
        else if(VAL_IS_FIELD(src))
          printf("FIELD");
        else if(VAL_IS_INT(src))
          printf("INT");
        else if(VAL_IS_FLOAT(src))
          printf("float");
	else if(VAL_IS_REVERSE(src))
	  printf("reverse");
        else printf("??");

        printf(" ");

        if(VAL_IS_TUPLE(dst))
          printf("tuple");
        else if(VAL_IS_REG(dst))
          printf("reg %d", VAL_REG(dst));
        else if(VAL_IS_HOST(dst))
          printf("host");
        else if(VAL_IS_FIELD(dst))
          printf("FIELD");
        else if(VAL_IS_INT(dst))
          printf("INT");
        else if(VAL_IS_FLOAT(dst))
          printf("float");
	else if(VAL_IS_REVERSE(dst))
	  printf("reverse");
        else printf("??");

	printf("\n");
      }
#endif
      size_t size = 0;

      Register *src = eval(MOVE_SRC(pc), &tuple, &old_pc, reg);
      Register *dst = eval_dst(MOVE_DST(pc), &old_pc, reg, &size);

      memcpy(dst, src, size);
      break;
      }

    case 0x40: // ALLOC
    case 0x50: // ALLOC
      {
      const unsigned char *old_pc = pc+2;
      tuple_t *dst;
      
#if defined(DEBUG_INSTRS) || defined(DEBUG_ALLOCS)
      {
        tuple_type type = ALLOC_TYPE(pc);
        printf("ALLOC %s\n", tuple_names[type]);
      }
#endif

      dst = eval(ALLOC_DST(pc), &tuple, &old_pc, reg);
			
      *dst = ALLOC_TUPLE(TYPE_SIZE(ALLOC_TYPE(pc)));
      memset(*dst, 0, TYPE_SIZE(ALLOC_TYPE(pc)));
      TUPLE_TYPE(*dst) = ALLOC_TYPE(pc);
      break;
      }

    case 0x60: // IF
    case 0x70: // IF
#ifdef DEBUG_INSTRS
      printf("IF reg %d ", IF_REG(pc));
#endif
      if (!reg[IF_REG(pc)]) {
#ifdef DEBUG_INSTRS
	printf("no\n");
#endif
	pc += IF_JUMP(pc);
	goto eval_loop;
      }

#ifdef DEBUG_INSTRS
      printf("yes\n");
#endif
      break;

    case 0x80: // REMOVE
    case 0x90: // REMOVE
      if (isNew > 0) {
        int reg_remove = REMOVE_REG(pc);
	int size = TYPE_SIZE(TUPLE_TYPE(MELD_CONVERT_REG_TO_PTR(reg[reg_remove])));

	tuple_handle(memcpy(malloc(size),MELD_CONVERT_REG_TO_PTR(reg[reg_remove]), size), -1, reg);
	reg[REMOVE_REG(pc)] = 0;
      }	
      break;

    case 0xa0: // ITER
      {
      const tuple_type type = ITER_TYPE(pc);
      int i, length;
      void **list;
      unsigned char *jump = pc + ITER_JUMP(pc);
      int size = TYPE_SIZE(type);
			
      /* produce a random ordering for all tuples of the appropriate type */
			
      if(TYPE_IS_PERSISTENT(type) && !TYPE_IS_AGG(type)) {
	/* persistent aggregate types not supported */
        persistent_set *persistents = &PERSISTENT[type];
        
        length = persistents->current;
        list = malloc(sizeof(tuple_t) * length);

        for(i = 0; i < length; i++) {
          int j = random() % (i + 1);
          
          list[i] = list[j];
          list[j] = persistents->array + i * size;
        }
      } else {
	/* non-persistent type */
	tuple_entry *entry = TUPLES[type].head;
		    
	length = queue_length(&TUPLES[ITER_TYPE(pc)]);
	list = malloc(sizeof(tuple_t) * length);
		    
	for (i = 0; i < length; i++) {
	  int j = random() % (i+1);

	  list[i] = list[j];
	  list[j] = entry->tuple;

	  entry = entry->next;
	}
      }
			
#ifdef DEBUG_INSTRS
      printf("ITER %s len=%d\n", tuple_names[type], length);
#endif

      if(length == 0) {
        /* no need to execute any further code, just jump! */
        pc = jump;
	goto eval_loop;
      }

      /* iterate over all tuples of the appropriate type */
      void *next_tuple;
      
      for (i = 0; i < length; i++) {
	next_tuple = list[i];

	unsigned char matched = 1;
	const unsigned char *tmppc;

        tmppc = pc + ITER_BASE;

        if(!ITER_MATCH_NONE(tmppc)) {
	  /* check to see if it matches */
          while (1) {
            const unsigned char *old_pc = tmppc + 2;
	    const unsigned char fieldnum = ITER_MATCH_FIELD(tmppc);
	    const unsigned char type_size = TYPE_ARG_SIZE(type, fieldnum);

            Register *field = GET_TUPLE_FIELD(next_tuple, fieldnum);
            Register *val = eval(ITER_MATCH_VAL(tmppc), &tuple, &old_pc, reg);
            
            matched = matched && (memcmp(field, val, type_size) == 0);

            if(ITER_MATCH_END(tmppc))
              break;

            tmppc = old_pc;
          }
	}

#ifdef DEBUG_INSTRS
	printf("MATCHED: %d %d\n", matched, length);
#endif
          
	if (matched) {
	  if (RET_RET == tuple_process(next_tuple, advance(pc), isNew, reg)) {
	    free(list);
	    return RET_RET;
	  }
	}
      }

      free(list);

      /* advance the pc to the end of the loop */
      pc = jump;
      goto eval_loop;
      break;
      }

    case 0xc0: // OP
    case 0xd0: // OP
    case 0xe0: // OP
    case 0xf0: // OP
      {
      const unsigned char *old_pc = pc+3;
			
#ifdef DEBUG_INSTRS
      printf("OP to %d\n", OP_DST(pc));
#endif

      Register *arg1, *arg2;
      
      arg1 = eval(OP_ARG1(pc), &tuple, &old_pc, reg);
      arg2 = eval(OP_ARG2(pc), &tuple, &old_pc, reg);
      
#ifdef DEBUG_INSTRS
      printf ("%ld", MELD_INT(arg1));
      printf ("OP");
      printf ("%ld", MELD_INT(arg2));
      printf ("\n");
#endif

      Register *dest = reg + OP_DST(pc);
      
      switch(OP_OP(pc)) {
      case OP_NEQI: *dest = (MELD_INT(arg1) != MELD_INT(arg2)); break;
      case OP_EQI: *dest = (MELD_INT(arg1) == MELD_INT(arg2)); break;
      case OP_LESSI: *dest = (MELD_INT(arg1) < MELD_INT(arg2)); break;
      case OP_LESSEQI: *dest = (MELD_INT(arg1) <= MELD_INT(arg2)); break;
      case OP_GREATERI: *dest = (MELD_INT(arg1) > MELD_INT(arg2)); break;
      case OP_GREATEREQI: *dest = (MELD_INT(arg1) >= MELD_INT(arg2)); break;
      case OP_MODI: MELD_INT(dest) = (MELD_INT(arg1) % MELD_INT(arg2)); break;
      case OP_PLUSI: MELD_INT(dest) = (MELD_INT(arg1) + MELD_INT(arg2)); break;
      case OP_MINUSI: MELD_INT(dest) = (MELD_INT(arg1) - MELD_INT(arg2)); break;
      case OP_TIMESI: MELD_INT(dest) = (MELD_INT(arg1) * MELD_INT(arg2)); break;
      case OP_DIVI: MELD_INT(dest) = (MELD_INT(arg1) / MELD_INT(arg2)); break;
      case OP_NEQF: *dest = (MELD_FLOAT(arg1) != MELD_FLOAT(arg2)); break;
      case OP_EQF: *dest = (MELD_FLOAT(arg1) == MELD_FLOAT(arg2)); break;
      case OP_LESSF: *dest = (MELD_FLOAT(arg1) < MELD_FLOAT(arg2)); break;
      case OP_LESSEQF: *dest = (MELD_FLOAT(arg1) <= MELD_FLOAT(arg2)); break;
      case OP_GREATERF: *dest = (MELD_FLOAT(arg1) > MELD_FLOAT(arg2)); break;
      case OP_GREATEREQF: *dest = (MELD_FLOAT(arg1) >= MELD_FLOAT(arg2)); break;
      case OP_MODF: MELD_FLOAT(dest) = fmod(MELD_FLOAT(arg1), MELD_FLOAT(arg2)); break;
      case OP_PLUSF: MELD_FLOAT(dest) = (MELD_FLOAT(arg1) + MELD_FLOAT(arg2)); break;
      case OP_MINUSF: MELD_FLOAT(dest) = (MELD_FLOAT(arg1) - MELD_FLOAT(arg2)); break;
      case OP_TIMESF: MELD_FLOAT(dest) = (MELD_FLOAT(arg1) * MELD_FLOAT(arg2)); break;
      case OP_DIVF: MELD_FLOAT(dest) = (MELD_FLOAT(arg1) / MELD_FLOAT(arg2)); break;
      case OP_NEQA: *dest = (MELD_PTR(arg1) != MELD_PTR(arg2)); break;
      case OP_EQA: *dest = (MELD_PTR(arg1) == MELD_PTR(arg2)); break;
      }
      break;
      }

    default:
      fprintf(stderr, "INVALID INSTRUCTION %u", *pc);
      assert(0);
      break;
    }
  }

  return RET_RET;
}
Beispiel #5
0
void *sync_src(void *arg)
{
	sync_thread_arg_t *tmparg = arg;
	int sock_fd = tmparg->sock_fd;
	io_sync_ctrl_block_t *dcp = tmparg->dcp;

	int ret;

	//iterate berkeley db, retrieving each record in turn.
	struct list_head key_head;
	struct hashtable *key_hash;
	DBC *cursorp;
	DBT dbt_key, dbt_data;
	dcp->dbp->cursor(dcp->dbp, NULL, &cursorp, 0);
	memset(&dbt_key, 0, sizeof(DBT));
	memset(&dbt_data, 0, sizeof(DBT));

	pthread_mutex_lock(&(dcp->io_lock));
	key_hash = create_hashtable(10000, hash_from_key_fn, keys_equal_fn);
	INIT_LIST_HEAD(&key_head);
	while ((ret = cursorp->c_get(cursorp, &dbt_key, &dbt_data, DB_NEXT)) == 0) {
		key_list_t *tmp = (key_list_t *)malloc(sizeof(key_list_t));
		memcpy(tmp->key, dbt_key.data, KEY_SIZE);
		list_add_tail(&(tmp->list_node), &key_head);
		if (!hashtable_insert(key_hash, tmp->key, tmp)) {
			perror("hash insert error!");
			return NULL;
		}
	}

	//close
	if (cursorp != NULL)
		cursorp->c_close(cursorp);

	pthread_mutex_unlock(&(dcp->io_lock));

	unsigned int max_packet_size = sizeof(msg_sync_t) + SECTION_SIZE;
	unsigned char *sock_buf = (unsigned char *)malloc(max_packet_size);
	DBT key, data;
	MD5_CTX md5_ctx;
	unsigned char tmp[BLOCK_INDEX_SIZE];
	msg_sync_t msg;
	unsigned int bi, fi = 0;
	off_t off1 = 0, off2 = 0;
	key_list_t *valuep;

	void *buf;
	if (posix_memalign(&buf, 512, SECTION_SIZE) != 0) {
		perror("posix_memalign error");
		return NULL;
	}

	int is_data_end = 0, is_block_end = 1;
	while (!is_data_end) {

		if (recv_task(sock_fd, sock_buf, max_packet_size) <= 0) {
			perror("rece_task error");
			return NULL;
		}

		msg = *((msg_sync_t *)sock_buf);
		unsigned char *sock_data;
		switch (msg.type) {
		//recv section md5 code
		case SYNC_SECTION_MD5:
			if (is_block_end || off2 >= BLOCK_SIZE) {
				perror("wrong section msg");
				return NULL;
			}

			sock_data = sock_buf + sizeof(msg_sync_t);

			//read src section data, and calc md5
			if (lseek(dcp->fd[fi], off1 + off2, SEEK_SET) == (off_t)-1) {
				perror("seek error");
				return NULL;
			}

			if (read(dcp->fd[fi], buf, SECTION_SIZE) != SECTION_SIZE) {
				perror("seek error");
				return NULL;
			}

			MD5Calc(&md5_ctx, (unsigned char *)buf, SECTION_SIZE);
#ifdef _SYNC_SRC_DEBUG__
			unsigned int kk;
			for (kk = 0; kk < 16; ++kk)
				printf("%02X", md5_ctx.digest[kk]);
			printf("\n");
#endif
			off2 += SECTION_SIZE;

			// compare to dest md5
			if (memcmp(md5_ctx.digest, sock_data, 16) == 0) {
				SEND_MSG(0, buf, SYNC_SECTION_SAME, "Can't send msg to client");
			} else {
				SEND_MSG(SECTION_SIZE, buf, SYNC_SECTION_DATA, "Can't send msg to client");
			}

			break;

		case SYNC_BLOCK_KEY:
			sock_data = sock_buf + sizeof(msg_sync_t);
#ifdef _SYNC_SRC_DEBUG__
			printf("%u %u ", msg.size, msg.type);
			int jj;
			for (jj = 0; jj < KEY_SIZE; ++jj) {
				printf("%u ", sock_data[jj]);
			}
			printf("\n");
#endif

			if ((valuep = hashtable_remove(key_hash, sock_data)) != NULL) {
				list_del(&(valuep->list_node));
				free(valuep);
			}

			//get block index by key
			memset(&key, 0, sizeof(DBT));
			key.data = sock_data;
			key.size = KEY_SIZE;

			memset(&data, 0, sizeof(DBT));
			data.data = tmp;
			data.ulen = BLOCK_INDEX_SIZE;
			data.flags = DB_DBT_USERMEM;

			ret = dcp->dbp->get(dcp->dbp, NULL, &key, &data, 0);
			if (ret == DB_NOTFOUND) {
				//reply SYNC_BLOCK_DELETE
				SEND_MSG(0, buf, SYNC_BLOCK_DELETE, "Can't send msg to client");
			} else if (ret) {
				printf("dbp->get error - %d\n", ret);
				perror("dbp->get error");
				return NULL;
			} else {
				//reply SYNC_BLOCK_CONTINUE
				bi = *((unsigned int *)tmp);
				fi = *(unsigned int *)(tmp + 4);
				off1 = bi;
				off1 = off1 * BLOCK_SIZE;
				off2 = 0;
				is_block_end = 0;

				SEND_MSG(0, buf, SYNC_BLOCK_CONTINUE,
					"log_deliver send error -can't send msg to client");
			}

			break;

		case SYNC_BLOCK_END:
			if (off2 != BLOCK_SIZE) {
				perror("wrong section");
				return NULL;
			}
			is_block_end = 1;
			SEND_MSG(0, buf, SYNC_OK, "Can't send msg to client");
			break;

		case SYNC_DATA_END:
			is_data_end = 1;
			break;

		default:
			perror("unknown sync msg code");
			return NULL;
		}
	}

   	//destroy hashtable but not free key and value
    hashtable_destroy(key_hash, 2);

	key_list_t *v;
    while (!list_empty(&key_head)) {
    	v = container_of(key_head.next, key_list_t , list_node);
#ifdef _SYNC_SRC_H__
		int kk;
		for (kk = 0; kk < 8; ++kk) printf("%u ", v->key[kk]);
		printf("\n");
#endif

		memset(&key, 0, sizeof(DBT));
		key.data = v->key;
		key.size = KEY_SIZE;

		memset(&data, 0, sizeof(DBT));
		data.data = tmp;
		data.ulen = BLOCK_INDEX_SIZE;
		data.flags = DB_DBT_USERMEM;

		ret = dcp->dbp->get(dcp->dbp, NULL, &key, &data, 0);
		if (ret == DB_NOTFOUND) {
			//do something here
			//key may be deleted
			list_del(key_head.next);
			continue;
		}

		bi = *(unsigned int *)tmp;
		fi = *(unsigned int *)(tmp + 4);

		//send keys
		SEND_MSG(KEY_SIZE, v->key, SYNC_BLOCK_KEY, "Can't send msg to client");

		//recv reply
		RECV_MSG(SYNC_BLOCK_CONTINUE, "recv key_reply error", "return type error");

		//new block, send section data
		off1 = bi;
		off1 = off1 * BLOCK_SIZE;
		for (off2 = 0; off2 < BLOCK_SIZE; off2 += SECTION_SIZE) {
			if (lseek(dcp->fd[fi], off1 + off2, SEEK_SET) == (off_t)-1) {
				perror("seek error");
				return NULL;
			}

			if (read(dcp->fd[fi], buf, SECTION_SIZE) != SECTION_SIZE) {
				perror("read error");
				return NULL;
			}

			//new block, send section data
			SEND_MSG(SECTION_SIZE, buf, SYNC_SECTION_DATA, "send section data failed");

			RECV_MSG(SYNC_OK, "recv section_reply error", "return type error");
		}

		//new block, send block end
		SEND_MSG(0, buf, SYNC_BLOCK_END, "send block end failed");
		
		RECV_MSG(SYNC_OK, "recv data_end_reply", "return type error");

    	list_del(key_head.next);
    }

	//new block, send data end
	SEND_MSG(0, buf, SYNC_DATA_END, "send data end failed");

	close(sock_fd);
	free(sock_buf);

//EXIT:

	return NULL;
}