#include "app_config.h" #include "typedef.h" #include "device/device.h" #include "fal.h" const struct fal_partition *fal_vm_partition_find(const char *name) { static void *fd; struct fal_partition *hd; const struct flashdb_partition_info *partition; list_for_each_flashdb_partition(partition) { if (!strcmp(name, partition->name)) { hd = (struct fal_partition *)zalloc(sizeof(struct fal_partition)); hd->fd = dev_open(partition->dev_name, NULL); fd = hd->fd; ASSERT(hd); hd->offset = partition->offset; hd->len = partition->len; return hd; } } ASSERT(0, "Please make sure %s it's in FAL partition table\n", name); return NULL; } #if 0 /*支付宝使用*/ REGISTER_FLASHDB_PARTITION(upay_partition) = { .name = "transit_fal", .dev_name = "transit_fal", .offset = 0, .len = 1024 * 1024, }; #endif /** * * read data from partition * * @param part partition * @param addr relative address for partition * @param buf read buffer * @param size read size * * @return >= 0: successful read data size * -1: error */ int fal_partition_read(const struct fal_partition *part, uint32_t addr, uint8_t *buf, size_t size) { u32 rets;//, reti; __asm__ volatile("%0 = rets":"=r"(rets)); /* printf("%s %x %x %x\n",__FUNCTION__,rets,addr,size); */ if (!part || !part->fd) { return -1; } return dev_bulk_read(part->fd, buf, addr + part->offset, size); } /** * write data to partition * * @param part partition * @param addr relative address for partition * @param buf write buffer * @param size write size * * @return >= 0: successful write data size * -1: error */ int fal_partition_write(const struct fal_partition *part, uint32_t addr, const uint8_t *buf, size_t size) { u32 rets;//, reti; __asm__ volatile("%0 = rets":"=r"(rets)); /* printf("%s %x %x %x\n",__FUNCTION__,rets,addr,size); */ if (!part || !part->fd) { return -1; } return dev_bulk_write(part->fd, (void *)buf, addr + part->offset, size); } /** * erase partition data * * @param part partition * @param addr relative address for partition * @param size erase size * * @return >= 0: successful erased data size * -1: error */ int fal_partition_erase(const struct fal_partition *part, uint32_t addr, size_t size) { if (!part || !part->fd) { return -1; } do { dev_ioctl(part->fd, IOCTL_ERASE_SECTOR, addr + part->offset); addr += 4096; size -= 4096; } while (size > 0); return 0; } /** * erase partition all data * * @param part partition * * @return >= 0: successful erased data size * -1: error */ /************************************************ * 测试用例 ***********************************************/ #include #if 1 void kvdb_basic_sample(fdb_kvdb_t kvdb) { struct fdb_blob blob; int boot_count = 0; FDB_INFO("==================== kvdb_basic_sample ====================\n"); #if 1 { /* GET the KV value */ /* get the "boot_count" KV value */ fdb_kv_get_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count))); /* the blob.saved.len is more than 0 when get the value successful */ if (blob.saved.len > 0) { FDB_INFO("get the 'boot_count' value is %d\n", boot_count); } else { FDB_INFO("get the 'boot_count' failed\n"); } } { /* CHANGE the KV value */ /* increase the boot count */ boot_count ++; /* change the "boot_count" KV's value */ fdb_kv_set_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count))); FDB_INFO("set the 'boot_count' value to %d\n", boot_count); } FDB_INFO("===========================================================\n"); #endif } #endif #if 1 void kvdb_type_string_sample(fdb_kvdb_t kvdb) { FDB_INFO("==================== kvdb_type_string_sample ====================\n"); { /* CREATE new Key-Value */ char temp_data[10] = "36C"; /* It will create new KV node when "temp" KV not in database. */ fdb_kv_set(kvdb, "tem", temp_data); FDB_INFO("create the 'temp' string KV, value is: %s\n", temp_data); } { /* GET the KV value */ char *return_value, temp_data[10] = { 0 }; /* Get the "temp" KV value. * NOTE: The return value saved in fdb_kv_get's buffer. Please copy away as soon as possible. */ return_value = fdb_kv_get(kvdb, "tem"); /* the return value is NULL when get the value failed */ if (return_value != NULL) { strncpy(temp_data, return_value, sizeof(temp_data)); FDB_INFO("get the 'temp' value is: %s\n", temp_data); } } { /* CHANGE the KV value */ char temp_data[10] = "38C"; /* change the "temp" KV's value to "38C" */ fdb_kv_set(kvdb, "tem", temp_data); FDB_INFO("set 'temp' value to %s\n", temp_data); } { /* DELETE the KV by name */ fdb_kv_del(kvdb, "tem"); FDB_INFO("delete the 'temp' finish\n"); } FDB_INFO("===========================================================\n"); } #endif #if 1 void kvdb_type_blob_sample(fdb_kvdb_t kvdb) { struct fdb_blob blob; FDB_INFO("==================== kvdb_type_blob_sample ====================\n"); { /* CREATE new Key-Value */ int temp_data = 36; /* It will create new KV node when "temp" KV not in database. * fdb_blob_make: It's a blob make function, and it will return the blob when make finish. */ fdb_kv_set_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data))); FDB_INFO("create the 'temp' blob KV, value is: %d\n", temp_data); } { /* GET the KV value */ int temp_data = 0; /* get the "temp" KV value */ fdb_kv_get_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data))); /* the blob.saved.len is more than 0 when get the value successful */ if (blob.saved.len > 0) { FDB_INFO("get the 'temp' value is: %d\n", temp_data); } } { /* CHANGE the KV value */ int temp_data = 38; /* change the "temp" KV's value to 38 */ fdb_kv_set_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data))); FDB_INFO("set 'temp' value to %d\n", temp_data); } { /* DELETE the KV by name */ fdb_kv_del(kvdb, "temp"); FDB_INFO("delete the 'temp' finish\n"); } FDB_INFO("===========================================================\n"); } #endif #if 0 void kvdb_tarversal_sample(fdb_kvdb_t kvdb) { struct fdb_kv_iterator iterator; fdb_kv_t cur_kv; struct fdb_blob blob; size_t data_size; uint8_t *data_buf; fdb_kv_iterator_init(kvdb, &iterator); while (fdb_kv_iterate(kvdb, &iterator)) { cur_kv = &(iterator.curr_kv); data_size = (size_t) cur_kv->value_len; data_buf = (uint8_t *) malloc(data_size); if (data_buf == NULL) { FDB_INFO("Error: malloc failed.\n"); break; } fdb_blob_read((fdb_db_t) kvdb, fdb_kv_to_blob(cur_kv, fdb_blob_make(&blob, data_buf, data_size))); put_buf(data_buf, data_size); /* * * balabala do what ever you like with blob... */ free(data_buf); } } #endif struct env_status { int temp; int humi; }; static bool query_cb(fdb_tsl_t tsl, void *arg); static bool query_by_time_cb(fdb_tsl_t tsl, void *arg); static bool set_status_cb(fdb_tsl_t tsl, void *arg); static bool query_cb(fdb_tsl_t tsl, void *arg) { struct fdb_blob blob; struct env_status status; fdb_tsdb_t db = arg; fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status)))); FDB_INFO("[query_cb] queried a TSL: time: %d, temp: %d, humi: %d\n", tsl->time, status.temp, status.humi); printf("!!!!!!! %x %x %x\n", blob.saved.meta_addr, blob.saved.addr, (unsigned int)blob.saved.len); return false; } static bool query_by_time_cb(fdb_tsl_t tsl, void *arg) { struct fdb_blob blob; struct env_status status; fdb_tsdb_t db = arg; fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status)))); FDB_INFO("[query_by_time_cb] queried a TSL: time: %d, temp: %d, humi: %d\n", tsl->time, status.temp, status.humi); return false; } static bool set_status_cb(fdb_tsl_t tsl, void *arg) { fdb_tsdb_t db = arg; FDB_INFO("set the TSL (time %d) status from %d to %d\n", tsl->time, tsl->status, FDB_TSL_USER_STATUS1); fdb_tsl_set_status(db, tsl, FDB_TSL_USER_STATUS1); return false; } void tsdb_sample(fdb_tsdb_t tsdb, int test) { struct fdb_blob blob; FDB_INFO("==================== tsdb_sample ====================\n"); { /* APPEND new TSL (time series log) */ struct env_status status; if (test) { /* append new log to TSDB */ status.temp = 36; status.humi = 85; fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status))); FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi); status.temp = 38; status.humi = 90; fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status))); FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi); } else { status.temp = 12; status.humi = 34; fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status))); FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi); status.temp = 56; status.humi = 78; fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status))); FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi); } } { /* QUERY the TSDB */ /* query all TSL in TSDB by iterator */ fdb_tsl_iter(tsdb, query_cb, tsdb); } { /* QUERY the TSDB by time */ /* prepare query time (from 1970-01-01 00:00:00 to 2020-05-05 00:00:00) */ struct tm tm_from = { .tm_year = 1970 - 1900, .tm_mon = 0, .tm_mday = 1, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 }; struct tm tm_to = { .tm_year = 2020 - 1900, .tm_mon = 4, .tm_mday = 5, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 }; time_t from_time = mktime(&tm_from), to_time = mktime(&tm_to); size_t count; /* query all TSL in TSDB by time */ fdb_tsl_iter_by_time(tsdb, from_time, to_time, query_by_time_cb, tsdb); /* query all FDB_TSL_WRITE status TSL's count in TSDB by time */ count = fdb_tsl_query_count(tsdb, from_time, to_time, FDB_TSL_WRITE); FDB_INFO("query count is: %u\n", (unsigned int)count); } { /* SET the TSL status */ /* Change the TSL status by iterator or time iterator * set_status_cb: the change operation will in this callback * * NOTE: The actions to modify the state must be in orderC. * like: FDB_TSL_WRITE -> FDB_TSL_USER_STATUS1 -> FDB_TSL_DELETED -> FDB_TSL_USER_STATUS2 * The intermediate states can also be ignored. * such as: FDB_TSL_WRITE -> FDB_TSL_DELETED */ fdb_tsl_iter(tsdb, set_status_cb, tsdb); } FDB_INFO("===========================================================\n"); } static uint32_t s_boot_count = 0; static time_t boot_time[10] = {0, 1, 2, 3}; static int counts = 0; static fdb_time_t get_time(void) { /* Using the counts instead of timestamp. * Please change this function to return RTC time. */ return ++counts; } static struct fdb_default_kv_node default_kv_table[] = { {"username", "armink", 0}, /* string KV */ {"password", "123456", 0}, /* string KV */ {"boot_count", &s_boot_count, sizeof(s_boot_count)}, /* int type KV */ {"boot_time", &boot_time, sizeof(boot_time)}, /* int array type KV */ {"12345678", "112233445556", 7}, /* int array type KV */ }; /* KVDB object */ static struct fdb_kvdb kvdb = { 0 }; /* TSDB object */ struct fdb_tsdb tsdb = { 0 }; /* TSDB object */ struct fdb_tsdb tsdb_call = { 0 }; int test_flashdb() { #ifdef FDB_USING_KVDB fdb_err_t result; { /* KVDB Sample */ struct fdb_default_kv default_kv; default_kv.kvs = default_kv_table; default_kv.num = sizeof(default_kv_table) / sizeof(default_kv_table[0]); /* set the lock and unlock function if you want */ /* fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_LOCK, lock); */ /* fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_UNLOCK, unlock); */ int sec_size = 4096 * 2; fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_SEC_SIZE, &sec_size); /* Key-Value database initialization * * &kvdb: database object * "env": database name * "fdb_kvdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table. * Please change to YOUR partition name. * &default_kv: The default KV nodes. It will auto add to KVDB when first initialize successfully. * NULL: The user data if you need, now is empty. */ result = fdb_kvdb_init(&kvdb, "env", "fdb_kvdb1", &default_kv, NULL); if (result != FDB_NO_ERR) { return -1; } /* run basic KV samples */ kvdb_basic_sample(&kvdb); /* run string KV samples */ kvdb_type_string_sample(&kvdb); /* run blob KV samples */ kvdb_type_blob_sample(&kvdb); /* kvdb_tarversal_sample(&kvdb); */ } #endif /* FDB_USING_KVDB */ #ifdef FDB_USING_TSDB { /* TSDB Sample */ /* set the lock and unlock function if you want */ /* fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_LOCK, lock); */ /* fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_UNLOCK, unlock); */ /* Time series database initialization * * &tsdb: database object * "log": database name * "fdb_tsdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table. * Please change to YOUR partition name. * get_time: The get current timestamp function. * 128: maximum length of each log * NULL: The user data if you need, now is empty. */ result = fdb_tsdb_init(&tsdb, "log", "fdb_tsdb1", get_time, 128, NULL); /* read last saved time for simulated timestamp */ fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_GET_LAST_TIME, &counts); if (result != FDB_NO_ERR) { return -1; } /* run TSDB sample */ tsdb_sample(&tsdb, 1); result = fdb_tsdb_init(&tsdb_call, "log_b", "fdb_tsdb2", get_time, 128, NULL); /* read last saved time for simulated timestamp */ fdb_tsdb_control(&tsdb_call, FDB_TSDB_CTRL_GET_LAST_TIME, &counts); if (result != FDB_NO_ERR) { ASSERT(0); return -1; } /* run TSDB sample */ tsdb_sample(&tsdb_call, 0); } #endif /* FDB_USING_TSDB */ return 0; /* extern void test_file(); */ /* test_file(); */ return 0; } /* #include "file_demo.c" */