diff options
author | Jeff Darcy <jdarcy@redhat.com> | 2014-01-30 22:10:19 +0000 |
---|---|---|
committer | Jeff Darcy <jdarcy@redhat.com> | 2014-02-11 13:57:04 +0000 |
commit | eaac191c29733173cbe2fbfd5604c26bd478002d (patch) | |
tree | d8c0b84f29a7f09ea25ffb47af409589c5d39270 /xlators/cluster/nsr-recon | |
parent | ef9d6ebe81e75463cd1ff0d3cf9a649bd2002421 (diff) |
nsr-recon: fix entry-count error when logs are preallocated
Change-Id: I48dc83f5ea5a47ec8ef7eaadf8ecbc5f2a725fd3
Signed-off-by: Jeff Darcy <jdarcy@redhat.com>
Diffstat (limited to 'xlators/cluster/nsr-recon')
-rw-r--r-- | xlators/cluster/nsr-recon/src/recon_xlator.c | 77 |
1 files changed, 65 insertions, 12 deletions
diff --git a/xlators/cluster/nsr-recon/src/recon_xlator.c b/xlators/cluster/nsr-recon/src/recon_xlator.c index b527633d8..da14aab93 100644 --- a/xlators/cluster/nsr-recon/src/recon_xlator.c +++ b/xlators/cluster/nsr-recon/src/recon_xlator.c @@ -114,26 +114,79 @@ static void get_frame(nsr_recon_private_t *priv, GF_ASSERT(0); } +#define ENTRY_SIZE 128 + +long +get_entry_count (char *path) +{ + int fd; + struct stat buf; + unsigned long entries = -1; + long min; /* last entry not known to be empty */ + long max; /* first entry known to be empty */ + long curr; + char entry[ENTRY_SIZE]; + void *err_label = &&done; + + fd = open(path,O_RDONLY); + if (fd < 0) { + goto *err_label; + } + err_label = &&close_fd; + + if (fstat(fd,&buf) < 0) { + goto *err_label; + } + + min = 0; + max = buf.st_size / ENTRY_SIZE; + printf("max = %ld\n",max); + + while ((min+1) < max) { + curr = (min + max) / 2; + printf("trying entry %ld\n",curr); + if (lseek(fd,curr*ENTRY_SIZE,SEEK_SET) < 0) { + goto *err_label; + } + if (read(fd,entry,sizeof(entry)) != sizeof(entry)) { + goto *err_label; + } + if ((entry[0] == '_') && (entry[1] == 'P')) { + min = curr; + } + else { + max = curr; + } + } + + entries = max; + +close_fd: + close(fd); +done: + return entries; +} + // Get the term info for the term number specified void nsr_recon_libchangelog_get_this_term_info(xlator_t *this, char *bp, int32_t term, nsr_recon_last_term_info_t *lt) { - struct stat buf; char path[PATH_MAX]; + long entries; bzero(lt, sizeof(nsr_recon_last_term_info_t)); lt->last_term = term; sprintf(path,"%s/%s%d",bp,"TERM.",term); - if (!stat(path, &buf) && (buf.st_size > 128)) { - if (buf.st_size <= 128) { - lt->first_index = 0; - lt->last_index = 0; - lt->commited_ops = 0; - } - else { - lt->first_index = 1; - lt->last_index = ((buf.st_size - 128)/128) + 1 ; - lt->commited_ops = lt->last_index - lt->first_index + 1; - } + entries = get_entry_count(path); + if (entries > 1) { + /* The first entry is actually a header. */ + lt->first_index = 1; + /* + * This seems wrong, because it means that last_index*128 will + * be exactly at EOF and commited_ops will be one greater than + * it should be. Maybe some other code makes the exact + * opposite mistake to compensate. + */ + lt->last_index = lt->commited_ops = (int)entries; } recon_main_log (this->name, GF_LOG_INFO, "for term=%d got first_index=%d last_index=%d commited_ops=%d\n", term, lt->first_index, lt->last_index, lt->commited_ops); |