// destructor void DataVault_dtor (DataVaultPtr self) { if (self) { DataCache_Destroy(self->cache); IOStream_Destroy(self->stream); WIPEPTR(self); } }
// destructor static void DataVault_dtor(DataVaultPtr self) { if (self) { DataCache_Destroy(self->cache); IOStream_Destroy(self->stream); esif_ccb_lock_uninit(&self->lock); WIPEPTR(self); } }
// Write DataVault to Disk eEsifError DataVault_WriteVault(DataVaultPtr self) { eEsifError rc = ESIF_OK; DataCacheEntryPtr pairPtr = NULL; IOStreamPtr diskStreamPtr = NULL; IOStreamPtr memStreamPtr = NULL; BytePtr memStreamBuffer = NULL; size_t memStreamBufSize = 0; UInt32 idx; DataCachePtr cacheClonePtr = NULL; if (FLAGS_TEST(self->flags, ESIF_SERVICE_CONFIG_STATIC | ESIF_SERVICE_CONFIG_READONLY)) { rc = ESIF_E_READONLY; goto exit; } if (self->stream->file.name == NULL || self->cache == NULL) { rc = ESIF_E_PARAMETER_IS_NULL; goto exit; } // // As the cache data can be modified while writing the data vault (due to // non-cached values), we create a clone of the current cache so that we can // fall back to it in case of a failure. // cacheClonePtr = DataCache_Clone(self->cache); if ((NULL == cacheClonePtr) && (self->cache != NULL)) { rc = ESIF_E_NO_MEMORY; goto exit; } // // Use a memory stream for creation before writing the final output to a file // memStreamPtr = IOStream_Create(); if (!memStreamPtr) { rc = ESIF_E_NO_MEMORY; goto exit; } if (IOStream_SetMemory(memStreamPtr, NULL, 0) != EOK) { rc = ESIF_E_NO_MEMORY; goto exit; } // // If any rows contain NOCACHE PERSIST values, we need to read them from the // original file before we overwrite it // diskStreamPtr = IOStream_Create(); if (diskStreamPtr == NULL) { rc = ESIF_E_NO_MEMORY; goto exit; } if (IOStream_Seek(memStreamPtr, sizeof(DataVaultHeader), SEEK_CUR) != EOK) { rc = ESIF_E_IO_ERROR; goto exit; } // // Write the key/value pairs to the memory stream for each data category // Fill in the data header for each category after the key/value pairs are written // Note: Only write persisted data // // Write All Persisted Rows from Sorted List to DataVault for (idx = 0; rc == ESIF_OK && idx < self->cache->size; idx++) { pairPtr = &self->cache->elements[idx]; if (!(pairPtr->flags & ESIF_SERVICE_CONFIG_PERSIST)) { continue; } rc = DataVault_WriteKeyValuePair(self, pairPtr, memStreamPtr); if (rc != ESIF_OK) { goto exit; } } // // Now go back and complete the headers // Fill in and write the main header // if (IOStream_Open(memStreamPtr) != EOK) { rc = ESIF_E_IO_ERROR; goto exit; } DataVaultHeader header = { 0 }; esif_ccb_memcpy(&header.signature, ESIFDV_SIGNATURE, sizeof(header.signature)); header.headersize = sizeof(header); header.version = ESIFDV_VERSION(1, 0, ESIFDV_REVISION); header.flags = self->flags; if (IOStream_Write(memStreamPtr, &header, sizeof(header)) != sizeof(header)) { rc = ESIF_E_IO_ERROR; goto exit; } memStreamBuffer = IOStream_GetMemoryBuffer(memStreamPtr); memStreamBufSize = IOStream_GetSize(memStreamPtr); // // Now write the memory stream to the disk // if (rc == ESIF_OK && IOStream_OpenFile(diskStreamPtr, self->stream->file.name, "wb") != EOK) { rc = ESIF_E_IO_OPEN_FAILED; goto exit; } if (rc == ESIF_OK && (IOStream_Write(diskStreamPtr, memStreamBuffer, memStreamBufSize) != memStreamBufSize)) { rc = ESIF_E_IO_ERROR; goto exit; } exit: IOStream_Destroy(diskStreamPtr); IOStream_Destroy(memStreamPtr); if (rc != ESIF_OK && cacheClonePtr != NULL) { DataCache_Destroy(self->cache); self->cache = cacheClonePtr; } else { DataCache_Destroy(cacheClonePtr); } return rc; }
/* Set */ eEsifError DataVault_SetValue ( DataVaultPtr self, EsifDataPtr path, EsifDataPtr value, esif_flags_t flags ) { eEsifError rc = ESIF_OK; DataCacheEntryPtr keypair; if (FLAGS_TEST(self->flags, ESIF_SERVICE_CONFIG_STATIC | ESIF_SERVICE_CONFIG_READONLY)) { return ESIF_E_READONLY; } // Ignore value for DELETEs if (FLAGS_TEST(flags, ESIF_SERVICE_CONFIG_DELETE)) { value = NULL; } // TODO: Locking // AUTO data types or AUTO_ALLOCATE are not allowed for SET if (value && (value->type == ESIF_DATA_AUTO || value->buf_len == ESIF_DATA_ALLOCATE)) { return ESIF_E_UNSUPPORTED_RESULT_DATA_TYPE; } // Write to Log DataVault_WriteLog(self, (flags & ESIF_SERVICE_CONFIG_DELETE ? "DELETE" : "SET"), self->name, path, flags, value); // Delete entire DataVault? if (strcmp((esif_string)path->buf_ptr, "*") == 0) { if (flags & ESIF_SERVICE_CONFIG_DELETE) { DataCache_Destroy(self->cache); if ((self->cache = DataCache_Create()) == NULL) { return ESIF_E_NO_MEMORY; } DataVault_WriteVault(self); return ESIF_OK; } return ESIF_E_NOT_SUPPORTED;// "*" is an invalid key value } // Read data from File // TODO: Change Parser Logic and Syntax instead if (value && value->buf_ptr && esif_ccb_strncmp((char*)value->buf_ptr, "<<", 2) == 0) { void *buffer = 0; UInt32 buflen = 0; if (DataVault_ReadFile(self, (char*)value->buf_ptr + 2, &buffer, &buflen) == ESIF_OK) { value->buf_ptr = buffer; if (value->type == ESIF_DATA_STRING) { buflen++; // Include Null Terminator } value->buf_len = value->data_len = buflen; } else { return ESIF_E_UNSPECIFIED; // TODO: File Not Found } } // Get the Data Row or create it if it does not exist keypair = DataCache_GetValue(self->cache, (esif_string)path->buf_ptr); if (keypair) { // Match Found // READONLY? if (keypair->flags & ESIF_SERVICE_CONFIG_READONLY) { rc = ESIF_E_READONLY; } // DELETE? else if (flags & ESIF_SERVICE_CONFIG_DELETE) { flags |= keypair->flags; DataCache_Delete(self->cache, (esif_string)path->buf_ptr); } else if (value && value->buf_ptr) { // UPDATE #ifdef ESIF_ATTR_OS_WINDOWS // Update Registry Value for REGKEY values if REGLINK is *NOT* specified in SET command if ((keypair->flags & ESIF_SERVICE_CONFIG_REGLINK) && !(flags & ESIF_SERVICE_CONFIG_REGLINK)) { keypair->value.type = value->type; rc = DataVault_WriteRegistry(self, (esif_string)keypair->value.buf_ptr, value); } else // ... #endif if (keypair->value.buf_len && value->data_len > keypair->value.buf_len) { rc = ESIF_E_NEED_LARGER_BUFFER; } else { keypair->flags = flags; keypair->value.type = value->type; keypair->value.data_len = value->data_len; // Replace the File Offset stored in buf_ptr with a copy of the data for updated NOCACHE values if (keypair->flags & ESIF_SERVICE_CONFIG_NOCACHE && keypair->value.buf_len == 0) { keypair->value.buf_ptr = esif_ccb_malloc(value->data_len); keypair->value.buf_len = value->data_len; } esif_ccb_memcpy(keypair->value.buf_ptr, value->buf_ptr, value->data_len); rc = ESIF_OK; } } } else if (value && value->buf_ptr && !(flags & ESIF_SERVICE_CONFIG_DELETE)) { // Copy Key/Value Pair to new Data Row EsifData newkey = {ESIF_DATA_STRING, esif_ccb_strdup((esif_string)path->buf_ptr), path->data_len, path->data_len}; EsifData newvalue = {value->type, esif_ccb_malloc(esif_ccb_max(value->buf_len, value->data_len)), value->data_len, value->data_len}; esif_ccb_memcpy(newvalue.buf_ptr, value->buf_ptr, value->data_len); DataCache_SetValue(self->cache, (esif_string)newkey.buf_ptr, newvalue, flags); esif_ccb_free(newkey.buf_ptr); } // If Persisted, Flush to disk if (rc == ESIF_OK && FLAGS_TEST(flags, ESIF_SERVICE_CONFIG_PERSIST)) { DataVault_WriteVault(self); } return rc; }