//////////////////////////////////////////////////// // SAVE ALL CONFIG TO EEPROM void storage_write_patch() { int len = 0; eeprom_write(0, MAGIC_COOKIE); int storage_ofs = 1; storage_write(global_storage(&len), len, &storage_ofs); storage_write(stack_storage(&len), len, &storage_ofs); storage_write(cv_storage(&len), len, &storage_ofs); storage_write(gate_storage(&len), len, &storage_ofs); }
// Clears the current page // Does not clear if: // - Previous page was cleared already // - Flash is entirely empty (no reason to clear) // storage_init() must be called first // // Returns: // 0 - Page was not cleared // 1 - Page was cleared uint8_t storage_clear_page() { // Flash is empty if ( current_page == 0 && current_storage_index == 0 ) { // Flash is full, needs to be erased which is the same as clearing a page if ( storage_erase_flash() ) { return 1; } return 0; } // Previous page was completely cleared if ( current_storage_index == 0 && cleared_block == 1 ) { return 0; } // Clear the rest of the blocks in the page // Write a 0'd out buffer as well uint8_t temp_buffer[STORAGE_SIZE]; memset( temp_buffer, 0, STORAGE_SIZE ); while ( current_storage_index != 0 ) { if ( storage_write( temp_buffer, 0, STORAGE_SIZE, 1 ) == 0 ) { // This is bad...not possible to recover without manually clearing print("Not enough room in buffer, failed to clear block."); return 0; } } return 1; }
// // store a room in the persistent database void worldStorePersistentRoom(WORLD_DATA *world, const char *key, ROOM_DATA *room) { static char fname[MAX_BUFFER]; static char dir1[SMALL_BUFFER]; static char dir2[SMALL_BUFFER]; if(!*key) return; unsigned long hash1 = pearson_hash8_1(key) % WORLD_BINS; unsigned long hash2 = pearson_hash8_2(key) % WORLD_BINS; *fname = '\0'; *dir1 = '\0'; *dir2 = '\0'; // make sure our hash bins exist sprintf(dir1, "%s/persistent/%lu", worldGetPath(world), hash1); if(!dir_exists(dir1)) mkdir(dir1, S_IRWXU | S_IRWXG); // and the second one as well sprintf(dir2, "%s/persistent/%lu/%lu", worldGetPath(world), hash1, hash2); if(!dir_exists(dir2)) mkdir(dir2, S_IRWXU | S_IRWXG); // now, store the room sprintf(fname, "%s/persistent/%lu/%lu/%s", worldGetPath(world), hash1, hash2, key); STORAGE_SET *set = roomStore(room); storage_write(set, fname); storage_close(set); // log_string("stored persistent room :: %s", fname); }
uint64_t storage_block_fill_write(struct storage_media *media, uint64_t start, uint64_t count, uint32_t fill_pattern) { if (storage_block_setup(media, start, count, 0) == 0) return 0; struct sd_mmc_ctrlr *ctrlr = media->ctrlr; uint64_t block_size = media->write_bl_len; /* * We allocate max 4 MiB buffer on heap and set it to fill_pattern and * perform mmc_write operation using this 4MiB buffer until requested * size on disk is written by the fill byte. * * 4MiB was chosen after repeating several experiments with the max * buffer size to be used. Using 1 lba i.e. block_size buffer results in * very large fill_write time. On the other hand, choosing 4MiB, 8MiB or * even 128 Mib resulted in similar write times. With 2MiB, the * fill_write time increased by several seconds. So, 4MiB was chosen as * the default max buffer size. */ uint64_t heap_lba = (4 * MiB) / block_size; /* * Actual allocated buffer size is minimum of three entities: * 1) 4MiB equivalent in lba * 2) count: Number of lbas to overwrite * 3) ctrlr->b_max: Max lbas that the block device allows write * operation on at a time. */ uint64_t buffer_lba = MIN(MIN(heap_lba, count), ctrlr->b_max); uint64_t buffer_bytes = buffer_lba * block_size; uint64_t buffer_words = buffer_bytes / sizeof(uint32_t); uint32_t *buffer = malloc(buffer_bytes); uint32_t *ptr = buffer; for (; buffer_words ; buffer_words--) *ptr++ = fill_pattern; uint64_t todo = count; int ret = 0; do { uint64_t curr_lba = MIN(buffer_lba, todo); if (storage_write(media, start, curr_lba, buffer) != curr_lba) goto cleanup; todo -= curr_lba; start += curr_lba; } while (todo > 0); ret = count; cleanup: free(buffer); return ret; }
uint8_t storage_save_settings() { uint8_t buffer[STORAGE_SIZE]; uint8_t offset = 0; for (uint8_t i=0; i<module_count; i++) { storage_modules[i]->onSave(); memcpy(buffer+offset, storage_modules[i]->settings, storage_modules[i]->size); offset += storage_modules[i]->size; } return storage_write(buffer, 0, sizeof(buffer), 0) == 1; }
// // write the set to file PyObject *PyStorageSet_write (PyObject *self, PyObject *args) { char *fname = NULL; if(!PyArg_ParseTuple(args, "s", &fname)) { PyErr_Format(PyExc_TypeError, "Filenames must be in string form"); return NULL; } storage_write(((PyStorageSet *)self)->set, fname); return Py_BuildValue("i", 1); }
void sp_write_1_svc_nb(void * pt, rozorpc_srv_ctx_t *req_ctx_p) { sp_write_arg_t * args = (sp_write_arg_t *) pt; static sp_write_ret_t ret; storage_t *st = 0; // Variable to be used in a later version. uint8_t version = 0; char *buf_bins; /* ** put the pointer to the bins (still in received buffer */ int position = storage_get_position_of_first_byte2write_from_write_req(); buf_bins = (char*)ruc_buf_getPayload(req_ctx_p->recv_buf); buf_bins+= position; DEBUG_FUNCTION; START_PROFILING_IO(write, args->nb_proj * rozofs_get_max_psize(args->layout) * sizeof (bin_t)); ret.status = SP_FAILURE; // Get the storage for the couple (cid;sid) if ((st = storaged_lookup(args->cid, args->sid)) == 0) { ret.sp_write_ret_t_u.error = errno; goto out; } // Write projections if (storage_write(st, args->layout, (sid_t *) args->dist_set, args->spare, (unsigned char *) args->fid, args->bid, args->nb_proj, version, &ret.sp_write_ret_t_u.file_size, (bin_t *) buf_bins) <= 0) { ret.sp_write_ret_t_u.error = errno; goto out; } ret.status = SP_SUCCESS; out: req_ctx_p->xmitBuf = req_ctx_p->recv_buf; req_ctx_p->recv_buf = NULL; rozorpc_srv_forward_reply(req_ctx_p,(char*)&ret); /* ** release the context */ rozorpc_srv_release_context(req_ctx_p); STOP_PROFILING(write); return ; }
// Start the write of a checksummed structure void data_services_write(void) { if (data_services_table_index >= mavlink_parameter_block_count) { if (data_services_user_callback != NULL) data_services_user_callback(true); data_services_user_callback = NULL; data_service_state = DATA_SERVICE_STATE_WAITING; return; } uint16_t size = serialise_items_to_buffer(data_services_table_index); if (size == 0) { if (data_services_user_callback != NULL) data_services_user_callback(false); data_services_user_callback = NULL; data_service_state = DATA_SERVICE_STATE_WAITING; return; } uint16_t handle = mavlink_parameter_blocks[data_services_table_index].data_storage_area; //data_services_calc_item_size(data_services_table_index); uint16_t type = DATA_STORAGE_CHECKSUM_STRUCT; // TODO: Check here if data handle is ok //storage_check_area_exists if ((type == DATA_STORAGE_CHECKSUM_STRUCT) && ((data_services_serialize_flags & mavlink_parameter_blocks[data_services_table_index].data_storage_flags) || (data_services_serialize_flags & STORAGE_FLAG_ALL))) { if (storage_write(handle, data_services_buffer, size, &data_services_write_callback) == true) { data_service_state = DATA_SERVICE_STATE_WRITE_WAITING; return; } } else { if (data_services_do_all_areas == true) data_services_table_index++; else { if (data_services_user_callback != NULL) data_services_user_callback(false); data_services_user_callback = NULL; data_service_state = DATA_SERVICE_STATE_WAITING; } } }
uint64_t storage_block_write(struct storage_media *media, uint64_t start, uint64_t count, const void *buffer) { const uint8_t *src = (const uint8_t *)buffer; if (storage_block_setup(media, start, count, 0) == 0) return 0; uint64_t todo = count; struct sd_mmc_ctrlr *ctrlr = media->ctrlr; do { uint64_t cur = MIN(todo, ctrlr->b_max); if (storage_write(media, start, cur, src) != cur) return 0; todo -= cur; start += cur; src += cur * media->write_bl_len; } while (todo > 0); return count; }
// // save all of the socials to disk // void save_socials() { STORAGE_SET *set = new_storage_set(); LIST *soc_list = newList(); // iterate across the social table and save all of the unique socials HASH_ITERATOR *hash_i = newHashIterator(social_table); const char *cmd = NULL; SOCIAL_DATA *data = NULL; ITERATE_HASH(cmd, data, hash_i) listPut(soc_list, data); deleteHashIterator(hash_i); store_list(set, "socials", gen_store_list(soc_list, socialStore)); deleteList(soc_list); // write the set storage_write(set, SOCIALS_FILE); // close the set storage_close(set); }
sp_status_ret_t *sp_write_1_svc(sp_write_arg_t * args, struct svc_req * req) { static sp_status_ret_t ret; storage_t *st = 0; DEBUG_FUNCTION; START_PROFILING_IO(write, args->nrb * rozofs_psizes[args->tid] * sizeof (bin_t)); ret.status = SP_FAILURE; if ((st = storaged_lookup(args->sid)) == 0) { ret.sp_status_ret_t_u.error = errno; goto out; } if (storage_write (st, args->fid, args->tid, args->bid, args->nrb, args->bins.bins_len, (bin_t *) args->bins.bins_val) != 0) { ret.sp_status_ret_t_u.error = errno; goto out; } ret.status = SP_SUCCESS; out: STOP_PROFILING(write); return &ret; }
static inline void main_menue (uint8_t cmd) { TLogfileBeaconPacket pkt; /* ignore non-printable characters */ if (cmd <= ' ') return; /* show key pressed */ debug_printf ("%c\n", cmd); /* map lower case to upper case */ if (cmd > 'a' && cmd < 'z') cmd -= ('a' - 'A'); switch (cmd) { case '?': case 'H': debug_printf ("\n" " *****************************************************\n" " * OpenBeacon Tag - Bluetooth Console\n" " * Version v" PROGRAM_VERSION "\n" " * (C) 2011 Milosch Meriac <*****@*****.**>\n" " *****************************************************\n" " * H,? - this help screen\n" " * S - Show device status\n" " *\n" " * E - Erase Storage\n" " * W - Test Write Storage\n" " * R - Test Read Storage\n" " * F - Test WriteFill Storage\n" " * M - write 3 times and read them\n" " *****************************************************\n" "\n"); break; case 'S': debug_printf ("\n" " *****************************************************\n" " * OpenBeacon Status Information *\n" " *****************************************************\n"); show_version (); spi_status (); acc_status (); storage_status (); debug_printf (" *****************************************************\n" "\n"); break; case 'M' : { uint32_t counter; debug_printf ("\nErasing Storage...\n\n"); storage_erase (); debug_printf ("\nWriting Khalil 3 times...\n"); counter = 0; const char data[] = "Khalil"; const uint8_t buffer[32]; while(counter < 3) { storage_write (counter*sizeof(buffer), sizeof (buffer), &data); counter ++; } debug_printf ("\n[DONE]\n"); debug_printf("\n reading the data...\n"); counter = 0; while(counter < 3) { storage_read (counter*sizeof(buffer), counter*sizeof(buffer) + sizeof (buffer), &buffer); hex_dump (buffer,0,sizeof (buffer)); counter++; } break; } case 'E': debug_printf ("\nErasing Storage...\n\n"); storage_erase (); g_storage_items = 0; break; case 'W': { const char hello[] = "Hello World!"; debug_printf ("\n * writing '%s' (%i bytes)\n", hello, sizeof (hello)); storage_write (0, sizeof (hello), &hello); } break; case 'R': { const uint8_t buffer[32]; debug_printf ("\n * reading %i bytes\n", sizeof (buffer)); storage_read (0, sizeof (buffer), &buffer); hex_dump (buffer, 0, sizeof (buffer)); } break; case 'F': { uint32_t counter; debug_printf ("\nErasing Storage...\n\n"); storage_erase (); debug_printf ("\nFilling Storage...\n"); counter = 0; while(counter < LOGFILE_STORAGE_SIZE) { pkt.time = htonl(counter); pkt.oid = htons(counter / sizeof(pkt)); pkt.strength = (counter / sizeof(pkt)) % MAX_POWER_LEVELS; pkt.crc = crc8 (((uint8_t *) & pkt), sizeof (pkt) - sizeof (pkt.crc)); storage_write (counter, sizeof (pkt), &pkt); counter += sizeof(pkt); } debug_printf ("\n[DONE]\n"); break; } default: debug_printf ("Unknown command '%c' - please press 'H' for help \n", cmd); } debug_printf ("\n# "); }
static void *storage_write_thread(void *arg) { void *storage = arg; // NOTE: ignoring overflow since that would take years of uptime in a // specific load pattern of never going to sleep. unsigned int backoff[MAX_NUMBER_OF_SLAB_CLASSES] = {0}; unsigned int counter = 0; useconds_t to_sleep = WRITE_SLEEP_MIN; logger *l = logger_create(); if (l == NULL) { fprintf(stderr, "Failed to allocate logger for storage compaction thread\n"); abort(); } pthread_mutex_lock(&storage_write_plock); while (1) { // cache per-loop to avoid calls to the slabs_clsid() search loop int min_class = slabs_clsid(settings.ext_item_size); bool do_sleep = true; counter++; if (to_sleep > WRITE_SLEEP_MAX) to_sleep = WRITE_SLEEP_MAX; for (int x = 0; x < MAX_NUMBER_OF_SLAB_CLASSES; x++) { bool did_move = false; bool mem_limit_reached = false; unsigned int chunks_free; int item_age; int target = settings.ext_free_memchunks[x]; if (min_class > x || (backoff[x] && (counter % backoff[x] != 0))) { // Long sleeps means we should retry classes sooner. if (to_sleep > WRITE_SLEEP_MIN * 10) backoff[x] /= 2; continue; } // Avoid extra slab lock calls during heavy writing. chunks_free = slabs_available_chunks(x, &mem_limit_reached, NULL, NULL); // storage_write() will fail and cut loop after filling write buffer. while (1) { // if we are low on chunks and no spare, push out early. if (chunks_free < target && mem_limit_reached) { item_age = 0; } else { item_age = settings.ext_item_age; } if (storage_write(storage, x, item_age)) { chunks_free++; // Allow stopping if we've done enough this loop did_move = true; do_sleep = false; if (to_sleep > WRITE_SLEEP_MIN) to_sleep /= 2; } else { break; } } if (!did_move) { backoff[x]++; } else if (backoff[x]) { backoff[x] /= 2; } } // flip lock so we can be paused or stopped pthread_mutex_unlock(&storage_write_plock); if (do_sleep) { usleep(to_sleep); to_sleep *= 2; } pthread_mutex_lock(&storage_write_plock); } return NULL; }