/** * timerqueue_add(Q, tv, ptr): * Add the pair (${tv}, ${ptr}) to the priority queue ${Q}. Returns a cookie * which can be passed to timerqueue_delete or timerqueue_increase. */ void * timerqueue_add(struct timerqueue * Q, const struct timeval * tv, void * ptr) { struct timerrec * r; /* Allocate (timeval, ptr) pair record. */ if ((r = malloc(sizeof(struct timerrec))) == NULL) goto err0; /* Fill in values. */ memcpy(&r->tv, tv, sizeof(struct timeval)); r->ptr = ptr; /* * Add the record to the heap. The value r->rc will be filled in * by setreccookie which will be called by ptrheap_add. */ if (ptrheap_add(Q->H, r)) goto err1; /* Success! */ return (r); err1: free(r); err0: /* Failure! */ return (NULL); }
/** * storage_findfiles(path): * Look for files named "blks_<16 hex digits>" in the directory ${path}. * Return an elastic queue of struct storage_file, in order of increasing * fileno. */ struct elasticqueue * storage_findfiles(const char * path) { struct stat sb; DIR * dir; struct dirent * dp; struct ptrheap * H; struct storage_file * sf; char * s; uint8_t fileno_exp[8]; struct elasticqueue * Q; /* Create a heap for holding storage_file structures. */ if ((H = ptrheap_init(fs_compar, NULL, NULL)) == NULL) goto err0; /* Create a queue for holding the structures in sorted order. */ if ((Q = elasticqueue_init(sizeof(struct storage_file))) == NULL) goto err1; /* Open the storage directory. */ if ((dir = opendir(path)) == NULL) { warnp("Cannot open storage directory: %s", path); goto err2; } /* * Look for files named "blks_<64-bit hexified first block #>" and * create storage_file structures for each. */ while ((errno = 0), ((dp = readdir(dir)) != NULL)) { /* Skip anything which isn't the right length. */ if (strlen(dp->d_name) != strlen("blks_0123456789abcdef")) continue; /* Skip anything which doesn't start with "blks_". */ if (strncmp(dp->d_name, "blks_", 5)) continue; /* Make sure the name has 8 hexified bytes and parse. */ if (unhexify(&dp->d_name[5], fileno_exp, 8)) continue; /* Construct a full path to the file and stat. */ if (asprintf(&s, "%s/%s", path, dp->d_name) == -1) { warnp("asprintf"); goto err3; } if (lstat(s, &sb)) { warnp("stat(%s)", s); goto err4; } /* Skip anything other than regular files. */ if (!S_ISREG(sb.st_mode)) goto next; /* Allocate a file_state structure. */ if ((sf = malloc(sizeof(struct storage_file))) == NULL) goto err4; /* Fill in file number and size. */ sf->fileno = be64dec(fileno_exp); sf->len = sb.st_size; /* Insert the file into the heap. */ if (ptrheap_add(H, sf)) goto err5; next: /* Free the full path to the file. */ free(s); } if (errno != 0) { warnp("Error reading storage directory: %s", path); goto err3; } /* Close the storage directory. */ while (closedir(dir)) { /* Retry if we were interrupted. */ if (errno == EINTR) continue; /* Oops, something bad happened. */ warnp("Error closing storage directory: %s", path); goto err2; } /* Suck structures from the heap into the queue. */ while ((sf = ptrheap_getmin(H)) != NULL) { if (elasticqueue_add(Q, sf)) goto err2; free(sf); ptrheap_deletemin(H); } /* Free the (now empty) heap. */ ptrheap_free(H); /* Success! */ return (Q); err5: free(sf); err4: free(s); err3: closedir(dir); err2: elasticqueue_free(Q); err1: while ((sf = ptrheap_getmin(H)) != NULL) { ptrheap_deletemin(H); free(sf); } ptrheap_free(H); err0: /* Failure! */ return (NULL); }