Page 1 of 1

nvs key_name problem

Posted: Tue Apr 04, 2017 1:14 pm
by ikerbelloso
Hi there,
I'm trying to implement a flash log of relevant events using nvs api. The idea was having nvs namespace were events are stored sequentially and then they can be retrieved when required.
For that I've set a name pattern, like "entryXX" where XX is the number of event. So each time a new event happens, y set a blob into the nvs space with key_name "entry00", "entry01"... etc..
Then I wanted to retrieve the events in reverse order and I was getting always one entry OK and then the following with ESP_ERR_NVS_NOT_FOUND error.
This is a simplified version of what I was doing... (I've removed some verification for simplicity)

Code: Select all

typedef struct{
	uint8_t var1;
	uint16_t var2;
	uint64_t var3;
	char var4[27];
}test_struct;

void Test_blob(void){

	nvs_handle out_handle;
	size_t test_size = sizeof(test_struct);
	char key_name[16];
	test_struct str1= {1,1000,1000000,"struct1"};
	test_struct str2= {2,2000,2000000,"struct2"};
	test_struct str3= {3,3000,3000000,"struct3"};
	test_struct str4= {4,4000,4000000,"struct4"};


	ESP_ERROR_CHECK(nvs_open("blob_test", NVS_READWRITE, &out_handle))

	sprintf(key_name,"str%x",1);
	ESP_ERROR_CHECK(nvs_set_blob(out_handle, key_name,(const void*)&str1,sizeof(test_struct)));
	sprintf(key_name,"str%x",2);
	ESP_ERROR_CHECK(nvs_set_blob(out_handle, key_name,(const void*)&str2,sizeof(test_struct)));
	sprintf(key_name,"str%x",3);
	ESP_ERROR_CHECK(nvs_set_blob(out_handle, key_name,(const void*)&str3,sizeof(test_struct)));
	sprintf(key_name,"str%x",4);
	ESP_ERROR_CHECK(nvs_set_blob(out_handle, key_name,(const void*)&str4,sizeof(test_struct)));

	memset(&str1,0x00,sizeof(test_struct));
	memset(&str2,0x00,sizeof(test_struct));
	memset(&str3,0x00,sizeof(test_struct));
	memset(&str4,0x00,sizeof(test_struct));

	sprintf(key_name,"str%x",4);
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,NULL,&test_size));
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,( void*)&str4,&test_size));

	sprintf(key_name,"str%x",3);
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,NULL,&test_size));
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,( void*)&str3,&test_size));

	sprintf(key_name,"str%x",2);
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,NULL,&test_size));
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,( void*)&str2,&test_size));

	sprintf(key_name,"str%x",1);
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,NULL,&test_size));
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,( void*)&str1,&test_size));

}
the error arises getting "str3" item size.
Then making some tests, I noticed that if I retrieved them into the input order, I had no problem:

Code: Select all

typedef struct{
	uint8_t var1;
	uint16_t var2;
	uint64_t var3;
	char var4[27];
}test_struct;

void Test_blob(void){

	nvs_handle out_handle;
	size_t test_size = sizeof(test_struct);
	char key_name[16];
	test_struct str1= {1,1000,1000000,"struct1"};
	test_struct str2= {2,2000,2000000,"struct2"};
	test_struct str3= {3,3000,3000000,"struct3"};
	test_struct str4= {4,4000,4000000,"struct4"};


	ESP_ERROR_CHECK(nvs_open("blob_test", NVS_READWRITE, &out_handle))

	sprintf(key_name,"str%x",1);
	ESP_ERROR_CHECK(nvs_set_blob(out_handle, key_name,(const void*)&str1,sizeof(test_struct)));
	sprintf(key_name,"str%x",2);
	ESP_ERROR_CHECK(nvs_set_blob(out_handle, key_name,(const void*)&str2,sizeof(test_struct)));
	sprintf(key_name,"str%x",3);
	ESP_ERROR_CHECK(nvs_set_blob(out_handle, key_name,(const void*)&str3,sizeof(test_struct)));
	sprintf(key_name,"str%x",4);
	ESP_ERROR_CHECK(nvs_set_blob(out_handle, key_name,(const void*)&str4,sizeof(test_struct)));

	memset(&str1,0x00,sizeof(test_struct));
	memset(&str2,0x00,sizeof(test_struct));
	memset(&str3,0x00,sizeof(test_struct));
	memset(&str4,0x00,sizeof(test_struct));

	sprintf(key_name,"str%x",1);
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,NULL,&test_size));
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,( void*)&str4,&test_size));

	sprintf(key_name,"str%x",2);
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,NULL,&test_size));
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,( void*)&str3,&test_size));

	sprintf(key_name,"str%x",3);
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,NULL,&test_size));
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,( void*)&str2,&test_size));

	sprintf(key_name,"str%x",4);
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,NULL,&test_size));
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name,( void*)&str1,&test_size));

}
Then Iv'e noticed that the nvs_get_blob function requires a "const char" as key name so switching to this approach :

Code: Select all

typedef struct{
	uint8_t var1;
	uint16_t var2;
	uint64_t var3;
	char var4[27];
}test_struct;

void Test_blob(void){

	nvs_handle out_handle;
	size_t test_size = sizeof(test_struct);
	const char key_name[4][5]={"str1","str2","str3","str4"};
	test_struct str1= {1,1000,1000000,"struct1"};
	test_struct str2= {2,2000,2000000,"struct2"};
	test_struct str3= {3,3000,3000000,"struct3"};
	test_struct str4= {4,4000,4000000,"struct4"};


	ESP_ERROR_CHECK(nvs_open("blob_test", NVS_READWRITE, &out_handle))


	ESP_ERROR_CHECK(nvs_set_blob(out_handle, key_name[0],(const void*)&str1,sizeof(test_struct)));
	ESP_ERROR_CHECK(nvs_set_blob(out_handle, key_name[1],(const void*)&str2,sizeof(test_struct)));
	ESP_ERROR_CHECK(nvs_set_blob(out_handle, key_name[2],(const void*)&str3,sizeof(test_struct)));
	ESP_ERROR_CHECK(nvs_set_blob(out_handle, key_name[3],(const void*)&str4,sizeof(test_struct)));

	memset(&str1,0x00,sizeof(test_struct));
	memset(&str2,0x00,sizeof(test_struct));
	memset(&str3,0x00,sizeof(test_struct));
	memset(&str4,0x00,sizeof(test_struct));

	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name[3],NULL,&test_size));
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name[3],( void*)&str4,&test_size));

	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name[2],NULL,&test_size));
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name[2],( void*)&str3,&test_size));

	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name[1] ,NULL,&test_size));
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name[1],( void*)&str2,&test_size));

	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name[0],NULL,&test_size));
	ESP_ERROR_CHECK(nvs_get_blob(out_handle, key_name[0],( void*)&str1,&test_size));
	
}
I solved the order problem using const cha* keynames but it forces me to have a huge const char keyname array to be able to save a useful number of events.
Is there any alternative solution to have dynamic key_names?
Thank you

Re: nvs key_name problem

Posted: Tue Apr 04, 2017 2:51 pm
by ESP_igrr
This is indeed a bug, thanks for the report. Will fix.