void FillMD5Area(uint8_t digest[], uint8_t id, const char passwd[], const uint8_t srcMD5[]) { uint8_t msgbuf[128]; // msgbuf = ‘id‘ + ‘passwd’ + ‘srcMD5’ int passlen = strlen(passwd); int msglen = 1 + passlen + 16; assert(sizeof(msgbuf) >= msglen); msgbuf[0] = id; memcpy(msgbuf+1, passwd, passlen); memcpy(msgbuf+1+passlen, srcMD5, 16); //(void)MD5(msgbuf, msglen, digest); MD5Calc(msgbuf, msglen, digest); }
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; }