diff options
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/ipc.c | 32 | ||||
-rw-r--r-- | src/server/net.c | 8 | ||||
-rw-r--r-- | src/server/server.c | 16 | ||||
-rw-r--r-- | src/server/server.h | 13 | ||||
-rw-r--r-- | src/server/utils.c | 62 |
5 files changed, 78 insertions, 53 deletions
diff --git a/src/server/ipc.c b/src/server/ipc.c index ebc907b..37ca36f 100644 --- a/src/server/ipc.c +++ b/src/server/ipc.c @@ -364,7 +364,8 @@ static int ipc_receive(int client_sock) GSList *iterator = NULL; struct tm *timeinfo; - char time_buff[64], rid[20], ipaddr[100]; +#define STRBUFLEN 100 + char strbuffer[STRBUFLEN]; dnbd3_ipc_t header; @@ -428,18 +429,27 @@ static int ipc_receive(int client_sock) for (iterator = _dnbd3_images; iterator; iterator = iterator->next) { const dnbd3_image_t *image = iterator->data; - sprintf(rid, "%d", image->rid); - timeinfo = localtime(&image->atime); - strftime(time_buff, 64, "%d.%m.%y %H:%M:%S", timeinfo); tmp_node = xmlNewNode(NULL, BAD_CAST "image"); if (tmp_node == NULL) goto get_info_reply_cleanup; xmlNewProp(tmp_node, BAD_CAST "name", BAD_CAST image->config_group); - xmlNewProp(tmp_node, BAD_CAST "atime", BAD_CAST time_buff); - xmlNewProp(tmp_node, BAD_CAST "rid", BAD_CAST rid); + timeinfo = localtime(&image->atime); + strftime(strbuffer, STRBUFLEN, "%d.%m.%y %H:%M:%S", timeinfo); + xmlNewProp(tmp_node, BAD_CAST "atime", BAD_CAST strbuffer); + sprintf(strbuffer, "%d", image->rid); + xmlNewProp(tmp_node, BAD_CAST "rid", BAD_CAST strbuffer); xmlNewProp(tmp_node, BAD_CAST "file", BAD_CAST image->file); - xmlNewProp(tmp_node, BAD_CAST "servers", BAD_CAST "???"); - xmlNewProp(tmp_node, BAD_CAST "cache", BAD_CAST image->cache_file); + xmlNewProp(tmp_node, BAD_CAST "servers", BAD_CAST "???"); // TODO + if (image->cache_file && image->cache_map) + { + xmlNewProp(tmp_node, BAD_CAST "cachefile", BAD_CAST image->cache_file); + int i, complete = 0, size = IMGSIZE_TO_MAPBYTES(image->filesize); + for (i = 0; i < size; ++i) + if (image->cache_map[i]) + complete += 100; + sprintf(strbuffer, "%d", complete / size); + xmlNewProp(tmp_node, BAD_CAST "cachefill", BAD_CAST image->cache_file); + } xmlAddChild(images_node, tmp_node); } // Clients @@ -455,9 +465,9 @@ static int ipc_receive(int client_sock) tmp_node = xmlNewNode(NULL, BAD_CAST "client"); if (tmp_node == NULL) goto get_info_reply_cleanup; - *ipaddr = '\0'; - inet_ntop(client->addrtype, client->ipaddr, ipaddr, 100); - xmlNewProp(tmp_node, BAD_CAST "ip", BAD_CAST ipaddr); + *strbuffer = '\0'; + inet_ntop(client->addrtype, client->ipaddr, strbuffer, STRBUFLEN); + xmlNewProp(tmp_node, BAD_CAST "ip", BAD_CAST strbuffer); xmlNewProp(tmp_node, BAD_CAST "file", BAD_CAST client->image->file); xmlAddChild(clients_node, tmp_node); } diff --git a/src/server/net.c b/src/server/net.c index b1a7b20..37ac0b4 100644 --- a/src/server/net.c +++ b/src/server/net.c @@ -160,6 +160,7 @@ void *dnbd3_handle_query(void *dnbd3_client) client_version = serializer_get_uint16(&payload); image_name = serializer_get_string(&payload); rid = serializer_get_uint16(&payload); + client->is_server = serializer_get_uint8(&payload); if (request.size < 3 || !image_name || client_version < MIN_SUPPORTED_CLIENT) { if (client_version < MIN_SUPPORTED_CLIENT) @@ -208,7 +209,8 @@ void *dnbd3_handle_query(void *dnbd3_client) else { client->image = image; - image->atime = time(NULL); // TODO: check if mutex is needed + if (!client->is_server) + image->atime = time(NULL); // TODO: check if mutex is needed if (image->cache_map && image->cache_file) image_cache = open(image->cache_file, O_RDWR); @@ -288,8 +290,8 @@ void *dnbd3_handle_query(void *dnbd3_client) // first make sure the whole requested part is in the local cache file while(cur_offset < last_offset) { - map_y = cur_offset >> 15; - map_x = (cur_offset >> 12) & 7; // mod 256 + map_y = cur_offset >> 15; // div 32768 + map_x = (cur_offset >> 12) & 7; // (X div 4096) mod 8 bit_mask = 0b00000001 << (map_x); cur_offset += 4096; diff --git a/src/server/server.c b/src/server/server.c index 28da0ae..1ca55fa 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -52,16 +52,16 @@ void dnbd3_print_help(char* argv_0) { printf("Usage: %s [OPTIONS]...\n", argv_0); printf("Start the DNBD3 server\n"); - printf("-f or --file \t\t Configuration file (default /etc/dnbd3-server.conf)\n"); + printf("-f or --file Configuration file (default /etc/dnbd3-server.conf)\n"); #ifdef _DEBUG - printf("-d or --delay \t\t Add a fake network delay of X µs\n"); + printf("-d or --delay Add a fake network delay of X µs\n"); #endif - printf("-n or --nodaemon \t Start server in foreground\n"); - printf("-r or --reload \t\t Reload configuration file\n"); - printf("-s or --stop \t\t Stop running dnbd3-server\n"); - printf("-i or --info \t\t Print connected clients and used images\n"); - printf("-H or --help \t\t Show this help text and quit\n"); - printf("-V or --version \t Show version and quit\n"); + printf("-n or --nodaemon Start server in foreground\n"); + printf("-r or --reload Reload configuration file\n"); + printf("-s or --stop Stop running dnbd3-server\n"); + printf("-i or --info Print connected clients and used images\n"); + printf("-H or --help Show this help text and quit\n"); + printf("-V or --version Show version and quit\n"); exit(0); } diff --git a/src/server/server.h b/src/server/server.h index 90aae5c..832777e 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -28,6 +28,15 @@ #include "../config.h" #include "../types.h" +// one byte in the map covers 8 4kib blocks, so 32kib per byte +// "+ (1 << 15) - 1" is required to account for the last bit of +// the image that is smaller than 32kib +// this would be the case whenever the image file size is not a +// multiple of 32kib (= the number of blocks is not divisible by 8) +// ie: if the image is 49152 bytes and you do 49152 >> 15 you get 1, +// but you actually need 2 bytes to have a complete cache map +#define IMGSIZE_TO_MAPBYTES(bytes) ((int)(((bytes) + (1 << 15) - 1) >> 15)) + typedef struct { char *config_group; // exact name of group in config file that represents this image @@ -42,13 +51,15 @@ typedef struct char working; // whether this image is considered working. local images are "working" if the local file exists, proxied images have to have at least one working upstream server or a complete local cache file time_t delete_soft; // unixtime telling when this image should be deleted. if there are still clients using this image it weill be kept, but new clients requesting the image will be rejected. 0 = never time_t delete_hard; // unixtime telling when this image should be deleted, no matter if there are still clients connected. 0 = never + uint8_t relayed; // TRUE if relayed from other server (needs dnbd3 client module loaded) } dnbd3_image_t; typedef struct { int sock; uint8_t ipaddr[16]; - uint8_t addrtype; // ip version (AF_INET or AF_INET6) + uint8_t addrtype; // ip version (AF_INET or AF_INET6) + uint8_t is_server; // TRUE if a server in proxy mode, FALSE if real client pthread_t thread; dnbd3_image_t *image; } dnbd3_client_t; diff --git a/src/server/utils.c b/src/server/utils.c index 665d96d..391992d 100644 --- a/src/server/utils.c +++ b/src/server/utils.c @@ -438,9 +438,9 @@ static dnbd3_image_t *prepare_image(char *image_name, int rid, char *image_file, image->config_group = strdup(image_name); image->rid = rid; - const char relayed = (image_file == NULL || image_file == '\0'); + image->relayed = (image_file == NULL || image_file == '\0'); - if (relayed) // Image is relayed (this server acts as proxy) + if (image->relayed) // Image is relayed (this server acts as proxy) { if (strchr(image_name, '/') == NULL) { @@ -508,45 +508,47 @@ static dnbd3_image_t *prepare_image(char *image_name, int rid, char *image_file, } else if (image->filesize > 0) { - const size_t map_len_bytes = (image->filesize + (1 << 15) - 1) >> 15; + const size_t map_len_bytes = IMGSIZE_TO_MAPBYTES(image->filesize); image->cache_map = calloc(map_len_bytes, sizeof(uint8_t)); // read cache map from file - // one byte in the map covers 8 4kib blocks, so 32kib per byte - // "+ (1 << 15) - 1" is required to account for the last bit of - // the image that is smaller than 32kib - // this would be the case whenever the image file size is not a - // multiple of 32kib (= the number of blocks is not divisible by 8) - // ie: if the image is 49152 bytes and you do 49152 >> 15 you get 1, - // but you actually need 2 bytes to have a complete cache map char tmp[strlen(image->cache_file) + 5]; strcpy(tmp, image->cache_file); strcat(tmp, ".map"); - fd = open(tmp, O_RDONLY); // TODO: Check if map file has expected size + fd = open(tmp, O_RDONLY); if (fd >= 0) { - read(fd, image->cache_map, map_len_bytes * sizeof(uint8_t)); - close(fd); - // If the whole image is cached, mark it as working right away without waiting for an upstream server - image->working = 1; - for (j = 0; j < map_len_bytes - 1; ++j) + const off_t size = lseek(fd, 0, SEEK_END); + if (size != map_len_bytes) { - if (image->cache_map[j] != 0xFF) + memlogf("[DEBUG] Cache-Map of %s is corrupted (%d != %d)", image_name, (int)size, (int)map_len_bytes); + } + else + { + lseek(fd, 0, SEEK_SET); + read(fd, image->cache_map, map_len_bytes); + // If the whole image is cached, mark it as working right away without waiting for an upstream server + image->working = 1; + for (j = 0; j < map_len_bytes - 1; ++j) { - image->working = 0; - break; + if (image->cache_map[j] != 0xFF) + { + image->working = 0; + break; + } } + const int blocks_in_last_byte = (image->filesize >> 12) & 7; + uint8_t last_byte = 0; + if (blocks_in_last_byte == 0) + last_byte = 0xFF; + else + for (j = 0; j < blocks_in_last_byte; ++j) + last_byte |= (1 << j); + if ((image->cache_map[map_len_bytes - 1] & last_byte) != last_byte) + image->working = 0; + else + memlogf("[INFO] Instantly publishing relayed image '%s' because the local cache copy is complete", image_name); } - const int blocks_in_last_byte = (image->filesize >> 12) & 7; - uint8_t last_byte = 0; - if (blocks_in_last_byte == 0) - last_byte = 0xFF; - else - for (j = 0; j < blocks_in_last_byte; ++j) - last_byte = (last_byte << 1) | 1; - if ((image->cache_map[map_len_bytes - 1] & last_byte) != last_byte) - image->working = 0; - else - memlogf("[INFO] Instantly publishing relayed image '%s' because the local cache copy is complete", image_name); + close(fd); } /* |