hyb-align/share_mem.c

167 lines
6.6 KiB
C

#include "share_mem.h"
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include "utils.h"
#define SHM_NAME_LIST "/shm_hybbwa_name_list"
#define SHM_HYB_PREFIX "/shm_hybbwa_"
#define SHM_NAME_LIST_SIZE 65535
static inline double get_GB(double bytes) { return bytes / 1024 / 1024 / 1024; }
// 根据文件路径获取文件名
const char* get_fn_from_path(const char* file_path) {
const char* fn = strrchr(file_path, '/');
if (fn != NULL)
return fn + 1;
return file_path;
}
// 将hybrid-index保存到share memrory里
int shm_keep_hyb(const char* idx_prefix) {
char full_path[MAX_PATH];
const char* file_name = NULL;
char share_name[MAX_PATH];
FILE* fp = NULL;
struct stat st;
int shmid, init_shm = 0, idx_name_len;
uint8_t *shm_idx_list, *mem;
uint16_t* shm_idx_cnt; // share memory中index数量
uint16_t* shm_byte_cnt; // 和占用的总内存数
double sec_time;
/////////////////
#define __shm_keep_hyb_code(suffix) \
sec_time = realtime(); \
strcat(strcpy(full_path, idx_prefix), suffix); \
file_name = get_fn_from_path(full_path); \
strcat(strcpy(share_name, SHM_HYB_PREFIX), get_fn_from_path(full_path)); \
if ((shmid = shm_open(share_name, O_CREAT | O_RDWR | O_EXCL, 0644)) < 0) { \
perror("shm_open()"); \
return -1; \
} \
err_check_true(stat(full_path, &st), 0, full_path); \
if (ftruncate(shmid, st.st_size) < 0) \
return -1; \
idx_name_len = 8 + strlen(file_name) + 1; \
if (idx_name_len + *shm_byte_cnt > SHM_NAME_LIST_SIZE) \
return -1; \
memcpy(shm_idx_list + *shm_byte_cnt, &st.st_size, 8); \
memcpy(shm_idx_list + *shm_byte_cnt + 8, file_name, idx_name_len - 8); \
*shm_byte_cnt += idx_name_len; \
*shm_idx_cnt += 1; \
mem = (uint8_t*)mmap(0, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0); \
fp = xopen(full_path, "r"); \
err_fread_noeof(mem, 1, st.st_size, fp); \
err_fclose(fp); \
munmap(mem, st.st_size); \
fprintf(stderr, "%s, %0.2f GB, %0.2f s\n", file_name, get_GB(st.st_size), realtime() - sec_time);
//////////////////////
// 打开保存索引名称的共享内存
if ((shmid = shm_open(SHM_NAME_LIST, O_RDWR, 0)) < 0) {
// 之前没有创建过,那就创建并初始化
shmid = shm_open(SHM_NAME_LIST, O_CREAT | O_RDWR | O_EXCL, 0644);
init_shm = 1;
}
if (shmid < 0 || ftruncate(shmid, SHM_NAME_LIST_SIZE) < 0)
return -1;
shm_idx_list = (uint8_t*)mmap(0, SHM_NAME_LIST_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
shm_idx_cnt = (uint16_t*)shm_idx_list;
shm_byte_cnt = (uint16_t*)(shm_idx_list + 2);
if (init_shm) { // 需要初始化share mem中的索引列表
memset(shm_idx_list, 0, SHM_NAME_LIST_SIZE);
*shm_byte_cnt = 4;
}
__shm_keep_hyb_code(HYB_PAC_SUFFIX);
__shm_keep_hyb_code(HYB_SA_SUFFIX);
__shm_keep_hyb_code(HYB_KMER_SUFFIX);
__shm_keep_hyb_code(HYB_DATA_SUFFIX);
return 0;
}
// 清理所有保存在share memory中的索引数据
int shm_clear_hyb() {
char share_name[MAX_PATH];
int shmid;
uint16_t *shm_idx_cnt, i;
char* shm_idx_list;
char* ptr;
if ((shmid = shm_open(SHM_NAME_LIST, O_RDONLY, 0)) < 0)
return -1;
shm_idx_list = (char*)mmap(0, SHM_NAME_LIST_SIZE, PROT_READ, MAP_SHARED, shmid, 0);
shm_idx_cnt = (uint16_t*)shm_idx_list;
for (i = 0, ptr = shm_idx_list + 4; i < *shm_idx_cnt; ++i) {
ptr += 8;
strcat(strcpy(share_name, SHM_HYB_PREFIX), ptr);
fprintf(stderr, "clear: %s\n", ptr);
shm_unlink(share_name);
ptr += strlen(ptr) + 1;
}
munmap(shm_idx_list, SHM_NAME_LIST_SIZE);
shm_unlink(SHM_NAME_LIST);
return 0;
}
// 从share mem中获取对应的索引数据
void* shm_get_index(const char* full_path) {
char share_name[MAX_PATH];
int shmid;
uint16_t *shm_idx_cnt, i;
char* shm_idx_list;
uint64_t idx_bytes;
char* ptr;
const char* file_name = get_fn_from_path(full_path);
if ((shmid = shm_open(SHM_NAME_LIST, O_RDONLY, 0)) < 0)
return NULL;
shm_idx_list = (char*)mmap(0, SHM_NAME_LIST_SIZE, PROT_READ, MAP_SHARED, shmid, 0);
shm_idx_cnt = (uint16_t*)shm_idx_list;
for (i = 0, ptr = shm_idx_list + 4; i < *shm_idx_cnt; ++i) {
memcpy(&idx_bytes, ptr, 8);
ptr += 8;
if (strcmp(ptr, file_name) == 0)
break;
ptr += strlen(ptr) + 1;
}
if (i == *shm_idx_cnt)
return NULL;
munmap(shm_idx_list, SHM_NAME_LIST_SIZE);
strcat(strcpy(share_name, SHM_HYB_PREFIX), file_name);
if ((shmid = shm_open(share_name, O_RDONLY, 0)) < 0)
return NULL;
return mmap(0, idx_bytes, PROT_READ, MAP_SHARED, shmid, 0);
}
// 列出共享内存中的hybrid-index
int list_shm_hyb_indices() {
int shmid;
uint16_t *shm_idx_cnt, i;
char* shm_idx_list;
char* ptr;
if ((shmid = shm_open(SHM_NAME_LIST, O_RDONLY, 0)) < 0) {
fprintf(stderr, "No shared hybrid index found.\n");
return -1;
}
shm_idx_list = (char*)mmap(0, SHM_NAME_LIST_SIZE, PROT_READ, MAP_SHARED, shmid, 0);
shm_idx_cnt = (uint16_t*)shm_idx_list;
fprintf(stderr, "Shared hybrid indices (%d):\n", *shm_idx_cnt);
for (i = 0, ptr = shm_idx_list + 4; i < *shm_idx_cnt; ++i) {
uint64_t idx_bytes;
memcpy(&idx_bytes, ptr, 8);
ptr += 8;
fprintf(stderr, "%s, %0.2f GB\n", ptr, get_GB(idx_bytes));
ptr += strlen(ptr) + 1;
}
munmap(shm_idx_list, SHM_NAME_LIST_SIZE);
return 0;
}