Exemple #1
0
struct tm *ol_sniff(ol_database *db, const char *key, size_t klen) {
    char _key[KEY_SIZE] = {'\0'};
    size_t _klen = 0;
    ol_bucket *bucket = ol_get_bucket(db, key, klen, &_key, &_klen);
    check_warn(_klen > 0, "Key length of zero not allowed.");

    if (bucket != NULL && bucket->expiration != NULL) {
        if (!_has_bucket_expired(bucket)) {
            return bucket->expiration;
        } else {
            /* It's dead, get rid of it. */
            check(ol_scoop(db, key, klen) == 0, "Could not delete a bucket!")
        }
    }

error:
    return NULL;
}
Exemple #2
0
int ol_aol_restore(ol_database *db)
{
	ol_string *command = NULL,
	           *key = NULL,
	            *value = NULL,
	             *ct = NULL,
	              *read_data_size = NULL,
	               *read_org_size = NULL;
	FILE *fd = fopen(db->aol_file, "r");
	check(fd, "Error opening file");
	while (!feof(fd)) {
		command = _ol_read_data(fd);
		check(command, "Error reading");
		/* Kind of a hack to check for EOF. If the struct is blank, then we
		 * read past EOF in _ol_read_data. feof is rarely useful I guess... */
		if (command->data == NULL) {
			free(command);
			break;
		}
		key = _ol_read_data(fd);
		check(key, "Error reading"); /* Everything needs a key */
		if (strncmp(command->data, "JAR", 3) == 0) {
			ct = _ol_read_data(fd);
			check(ct, "Error reading");
			read_org_size = _ol_read_data(fd);
			check(read_org_size, "Error reading");
			read_data_size = _ol_read_data(fd);
			check(read_data_size, "Error reading");
			value = _ol_read_data(fd);
			check(value, "Error reading");
			size_t original_size = (size_t)strtol(read_org_size->data, NULL, 10);
			size_t compressed_size = (size_t)strtol(read_data_size->data, NULL, 10);
			size_t data_offset = (size_t)strtol(value->data, NULL, 10);
			/* Pointer in the values file to where the data for this command
			 * should be. */
			unsigned char *data_ptr = db->values + data_offset;
			/* Short circuit check to see if the memory in the location is all
			 * null. */
			int memory_is_not_null = 0;
			int i = 0;
			for (; i < compressed_size; i++) {
				if ('\0' != data_ptr[i]) {
					debug("Data is not null on %zu.", data_offset + i);
					memory_is_not_null = 1;
					break;
				}
			}
			if (memory_is_not_null) {
				/* Turns out that in rare cases LZ4 will compress to exactly
				 * the same size as it's starting string. This means we can't
				 * just check to see if original_size != compressed_size, so
				 * instead we first attempt to decompress and check how many
				 * chars were processed.
				 */
				char tmp_data[original_size];
				char *ret = memset(&tmp_data, 0, original_size);
				check(ret == tmp_data, "Could not initialize tmp_data parameter.");
				int processed = LZ4_decompress_fast((const char*)data_ptr, (char *)tmp_data, original_size);
				if (processed == compressed_size)
					ol_jar_ct(db, key->data, key->dlen, (unsigned char*)tmp_data, original_size, ct->data, ct->dlen);
				else {
					if (original_size != compressed_size)
						ol_log_msg(LOG_WARN, "Could not decompress data that is probably compressed. Data may have been deleted.");
					/* Now that we've tried to decompress and failed, send off the raw data instead. */
					ol_jar_ct(db, key->data, key->dlen, data_ptr, compressed_size, ct->data, ct->dlen);
				}
			}
#ifdef DEBUG
			/* This happens a lot and isn't bad, so I'm commenting it out. */
			else
				ol_log_msg(LOG_WARN, "No data in values file that corresponds with this key. Key has been deleted or updated.");
#endif
			/* Important: Set the new offset to compressed_size + data_offset.
			 * We need to do this because compaction/squishing will leave holes
			 * in the data that we need to account for during replay.
			 */
			db->val_size = compressed_size + data_offset;
			ol_string_free(&read_org_size);
			ol_string_free(&read_data_size);
			ol_string_free(&ct);
			ol_string_free(&value);
		} else if (strncmp(command->data, "SCOOP", 5) == 0)
			ol_scoop(db, key->data, key->dlen);
		else if (strncmp(command->data, "SPOIL", 5) == 0) {
			ol_string *spoil = _ol_read_data(fd);
			check(spoil != NULL, "Could not read the rest of SPOIL command for AOL.");
			struct tm time = {0};
			_deserialize_time(&time, spoil->data);
			check(spoil, "Error reading");
			ol_spoil(db, key->data, key->dlen, &time);
			ol_string_free(&spoil);
		}
		/* Strip the newline char after each "record" */
		char c;
		check(fread(&c, 1, 1, fd) != 0, "Error reading");
		check(c == '\n', "Could not strip newline");
		ol_string_free(&command);
		ol_string_free(&key);
	}
	fclose(fd);
	return 0;
error:
	ol_log_msg(LOG_ERR, "Restore failed. Corrupt AOL?");
	/* Free all the stuff */
	ol_string_free(&command);
	ol_string_free(&key);
	ol_string_free(&value);
	ol_string_free(&ct);
	ol_string_free(&read_org_size);
	ol_string_free(&read_data_size);
	if (fd != NULL)
		fclose(fd);
	return -1;
}