mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
storage: Introduce storage coordination thread and infrastructure for parallel next-generation IndexedDB implementation (#40661)
This PR introduces a new storage coordination thread, intended to serve as the central point for managing all current and future storage endpoints in Servo. In addition to the new coordination thread, this PR also lays the infrastructure required to develop a parallel, next-generation IndexedDB implementation under the indexeddb_next feature flag living on a separate branch. Testing: Unit and WPT tests continue to pass --------- Signed-off-by: Jan Varga <jvarga@igalia.com>
This commit is contained in:
@@ -167,7 +167,8 @@ use serde::{Deserialize, Serialize};
|
||||
use servo_config::{opts, pref};
|
||||
use servo_url::{Host, ImmutableOrigin, ServoUrl};
|
||||
use storage_traits::StorageThreads;
|
||||
use storage_traits::indexeddb_thread::{IndexedDBThreadMsg, SyncOperation};
|
||||
use storage_traits::client_storage::ClientStorageThreadMessage;
|
||||
use storage_traits::indexeddb::{IndexedDBThreadMsg, SyncOperation};
|
||||
use storage_traits::webstorage_thread::{StorageType, WebStorageThreadMsg};
|
||||
use style::global_style_data::StyleThreadPool;
|
||||
#[cfg(feature = "webgpu")]
|
||||
@@ -2592,10 +2593,12 @@ where
|
||||
// Channels to receive signals when threads are done exiting.
|
||||
let (core_ipc_sender, core_ipc_receiver) =
|
||||
ipc::channel().expect("Failed to create IPC channel!");
|
||||
let (storage_ipc_sender, storage_ipc_receiver) =
|
||||
generic_channel::channel().expect("Failed to create IPC channel!");
|
||||
let (client_storage_generic_sender, client_storage_generic_receiver) =
|
||||
generic_channel::channel().expect("Failed to create generic channel!");
|
||||
let (indexeddb_ipc_sender, indexeddb_ipc_receiver) =
|
||||
ipc::channel().expect("Failed to create IPC channel!");
|
||||
let (web_storage_generic_sender, web_storage_generic_receiver) =
|
||||
generic_channel::channel().expect("Failed to create generic channel!");
|
||||
|
||||
debug!("Exiting core resource threads.");
|
||||
if let Err(e) = self
|
||||
@@ -2613,14 +2616,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
debug!("Exiting storage resource threads.");
|
||||
debug!("Exiting client storage thread.");
|
||||
if let Err(e) = generic_channel::GenericSend::send(
|
||||
&self.public_storage_threads,
|
||||
WebStorageThreadMsg::Exit(storage_ipc_sender),
|
||||
ClientStorageThreadMessage::Exit(client_storage_generic_sender),
|
||||
) {
|
||||
warn!("Exit storage thread failed ({})", e);
|
||||
warn!("Exit client storage thread failed ({})", e);
|
||||
}
|
||||
|
||||
debug!("Exiting indexeddb resource threads.");
|
||||
if let Err(e) =
|
||||
self.public_storage_threads
|
||||
@@ -2630,6 +2632,13 @@ where
|
||||
{
|
||||
warn!("Exit indexeddb thread failed ({})", e);
|
||||
}
|
||||
debug!("Exiting web storage thread.");
|
||||
if let Err(e) = generic_channel::GenericSend::send(
|
||||
&self.public_storage_threads,
|
||||
WebStorageThreadMsg::Exit(web_storage_generic_sender),
|
||||
) {
|
||||
warn!("Exit web storage thread failed ({})", e);
|
||||
}
|
||||
|
||||
#[cfg(feature = "bluetooth")]
|
||||
{
|
||||
@@ -2698,12 +2707,15 @@ where
|
||||
if let Err(e) = core_ipc_receiver.recv() {
|
||||
warn!("Exit resource thread failed ({:?})", e);
|
||||
}
|
||||
if let Err(e) = storage_ipc_receiver.recv() {
|
||||
warn!("Exit storage thread failed ({:?})", e);
|
||||
if let Err(e) = client_storage_generic_receiver.recv() {
|
||||
warn!("Exit client storage thread failed ({:?})", e);
|
||||
}
|
||||
if let Err(e) = indexeddb_ipc_receiver.recv() {
|
||||
warn!("Exit indexeddb thread failed ({:?})", e);
|
||||
}
|
||||
if let Err(e) = web_storage_generic_receiver.recv() {
|
||||
warn!("Exit web storage thread failed ({:?})", e);
|
||||
}
|
||||
|
||||
debug!("Shutting-down IPC router thread in constellation.");
|
||||
ROUTER.shutdown();
|
||||
|
||||
@@ -286,7 +286,7 @@ pub(crate) struct GlobalScope {
|
||||
resource_threads: ResourceThreads,
|
||||
|
||||
/// Associated resource threads for use by DOM objects like XMLHttpRequest,
|
||||
/// including indexeddb_thread and storage_thread
|
||||
/// including indexeddb thread and storage_thread
|
||||
#[no_trace]
|
||||
storage_threads: StorageThreads,
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ use dom_struct::dom_struct;
|
||||
use js::jsapi::Heap;
|
||||
use js::jsval::{JSVal, UndefinedValue};
|
||||
use js::rust::MutableHandleValue;
|
||||
use storage_traits::indexeddb_thread::{IndexedDBKeyRange, IndexedDBKeyType, IndexedDBRecord};
|
||||
use storage_traits::indexeddb::{IndexedDBKeyRange, IndexedDBKeyType, IndexedDBRecord};
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::IDBCursorBinding::{
|
||||
@@ -25,7 +25,7 @@ use crate::dom::indexeddb::idbindex::IDBIndex;
|
||||
use crate::dom::indexeddb::idbobjectstore::IDBObjectStore;
|
||||
use crate::dom::indexeddb::idbrequest::IDBRequest;
|
||||
use crate::dom::indexeddb::idbtransaction::IDBTransaction;
|
||||
use crate::indexed_db::key_type_to_jsval;
|
||||
use crate::indexeddb::key_type_to_jsval;
|
||||
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
|
||||
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
use js::rust::MutableHandleValue;
|
||||
use storage_traits::indexeddb_thread::IndexedDBKeyRange;
|
||||
use storage_traits::indexeddb::IndexedDBKeyRange;
|
||||
|
||||
use crate::dom::bindings::codegen::Bindings::IDBCursorBinding::IDBCursorDirection;
|
||||
use crate::dom::bindings::codegen::Bindings::IDBCursorWithValueBinding::IDBCursorWithValueMethods;
|
||||
|
||||
@@ -8,7 +8,7 @@ use base::IpcSend;
|
||||
use dom_struct::dom_struct;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use profile_traits::ipc;
|
||||
use storage_traits::indexeddb_thread::{IndexedDBThreadMsg, KeyPath, SyncOperation};
|
||||
use storage_traits::indexeddb::{IndexedDBThreadMsg, KeyPath, SyncOperation};
|
||||
use stylo_atoms::Atom;
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
@@ -30,7 +30,7 @@ use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::indexeddb::idbobjectstore::IDBObjectStore;
|
||||
use crate::dom::indexeddb::idbtransaction::IDBTransaction;
|
||||
use crate::dom::indexeddb::idbversionchangeevent::IDBVersionChangeEvent;
|
||||
use crate::indexed_db::is_valid_key_path;
|
||||
use crate::indexeddb::is_valid_key_path;
|
||||
use crate::script_runtime::CanGc;
|
||||
|
||||
#[dom_struct]
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::dom::bindings::root::DomRoot;
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::indexeddb::idbopendbrequest::IDBOpenDBRequest;
|
||||
use crate::indexed_db::convert_value_to_key;
|
||||
use crate::indexeddb::convert_value_to_key;
|
||||
use crate::script_runtime::CanGc;
|
||||
|
||||
#[dom_struct]
|
||||
|
||||
@@ -8,13 +8,13 @@ use js::rust::HandleValue;
|
||||
use script_bindings::codegen::GenericBindings::IDBKeyRangeBinding::IDBKeyRangeMethods;
|
||||
use script_bindings::root::DomRoot;
|
||||
use script_bindings::script_runtime::CanGc;
|
||||
use storage_traits::indexeddb_thread::IndexedDBKeyRange;
|
||||
use storage_traits::indexeddb::IndexedDBKeyRange;
|
||||
|
||||
use crate::dom::bindings::error::{Error, Fallible};
|
||||
use crate::dom::bindings::import::module::SafeJSContext;
|
||||
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::indexed_db::{convert_value_to_key, key_type_to_jsval};
|
||||
use crate::indexeddb::{convert_value_to_key, key_type_to_jsval};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct IDBKeyRange {
|
||||
|
||||
@@ -10,7 +10,7 @@ use js::rust::HandleValue;
|
||||
use profile_traits::ipc;
|
||||
use script_bindings::conversions::SafeToJSValConvertible;
|
||||
use script_bindings::error::ErrorResult;
|
||||
use storage_traits::indexeddb_thread::{
|
||||
use storage_traits::indexeddb::{
|
||||
AsyncOperation, AsyncReadOnlyOperation, AsyncReadWriteOperation, IndexedDBKeyType,
|
||||
IndexedDBThreadMsg, SyncOperation,
|
||||
};
|
||||
@@ -36,7 +36,7 @@ use crate::dom::indexeddb::idbcursor::{IDBCursor, IterationParam, ObjectStoreOrI
|
||||
use crate::dom::indexeddb::idbcursorwithvalue::IDBCursorWithValue;
|
||||
use crate::dom::indexeddb::idbrequest::IDBRequest;
|
||||
use crate::dom::indexeddb::idbtransaction::IDBTransaction;
|
||||
use crate::indexed_db::{
|
||||
use crate::indexeddb::{
|
||||
self, ExtractionResult, convert_value_to_key, convert_value_to_key_range, extract_key,
|
||||
};
|
||||
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
|
||||
@@ -256,7 +256,7 @@ impl IDBObjectStore {
|
||||
return Err(Error::InvalidState(None));
|
||||
};
|
||||
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
let (sender, receiver) = indexeddb::create_channel(self.global());
|
||||
|
||||
// Step 12. Let operation be an algorithm to run store a record into an object store with store, clone, key, and no-overwrite flag.
|
||||
// Step 13. Return the result (an IDBRequest) of running asynchronously execute a request with handle and operation.
|
||||
@@ -341,7 +341,7 @@ impl IDBObjectStore {
|
||||
primary_key: None,
|
||||
count: None,
|
||||
};
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
let (sender, receiver) = indexeddb::create_channel(self.global());
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
AsyncOperation::ReadOnly(AsyncReadOnlyOperation::Iterate {
|
||||
@@ -393,7 +393,7 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
|
||||
let serialized_query = convert_value_to_key_range(cx, query, Some(true));
|
||||
// Step 7. Let operation be an algorithm to run delete records from an object store with store and range.
|
||||
// Step 8. Return the result (an IDBRequest) of running asynchronously execute a request with this and operation.
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
let (sender, receiver) = indexeddb::create_channel(self.global());
|
||||
serialized_query.and_then(|key_range| {
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
@@ -422,7 +422,7 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
|
||||
|
||||
// Step 6. Let operation be an algorithm to run clear an object store with store.
|
||||
// Step 7. Return the result (an IDBRequest) of running asynchronously execute a request with this and operation.
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
let (sender, receiver) = indexeddb::create_channel(self.global());
|
||||
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
@@ -449,7 +449,7 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
|
||||
|
||||
// Step 6. Let operation be an algorithm to run retrieve a value from an object store with the current Realm record, store, and range.
|
||||
// Step 7. Return the result (an IDBRequest) of running asynchronously execute a request with this and operation.
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
let (sender, receiver) = indexeddb::create_channel(self.global());
|
||||
serialized_query.and_then(|q| {
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
@@ -481,7 +481,7 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
|
||||
// Step 6. Run the steps to asynchronously execute a request and return the IDBRequest created by these steps.
|
||||
// The steps are run with this object store handle as source and the steps to retrieve a key from an object
|
||||
// store as operation, using store and range.
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
let (sender, receiver) = indexeddb::create_channel(self.global());
|
||||
serialized_query.and_then(|q| {
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
@@ -518,7 +518,7 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
|
||||
// Step 6. Run the steps to asynchronously execute a request and return the IDBRequest created by these steps.
|
||||
// The steps are run with this object store handle as source and the steps to retrieve a key from an object
|
||||
// store as operation, using store and range.
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
let (sender, receiver) = indexeddb::create_channel(self.global());
|
||||
serialized_query.and_then(|q| {
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
@@ -556,7 +556,7 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
|
||||
// Step 6. Run the steps to asynchronously execute a request and return the IDBRequest created by these steps.
|
||||
// The steps are run with this object store handle as source and the steps to retrieve a key from an object
|
||||
// store as operation, using store and range.
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
let (sender, receiver) = indexeddb::create_channel(self.global());
|
||||
serialized_query.and_then(|q| {
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
@@ -588,7 +588,7 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
|
||||
|
||||
// Step 6. Let operation be an algorithm to run count the records in a range with store and range.
|
||||
// Step 7. Return the result (an IDBRequest) of running asynchronously execute a request with this and operation.
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
let (sender, receiver) = indexeddb::create_channel(self.global());
|
||||
serialized_query.and_then(|q| {
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
|
||||
@@ -9,7 +9,7 @@ use js::jsval::UndefinedValue;
|
||||
use js::rust::HandleValue;
|
||||
use profile_traits::ipc;
|
||||
use script_bindings::conversions::SafeToJSValConvertible;
|
||||
use storage_traits::indexeddb_thread::{BackendResult, IndexedDBThreadMsg, SyncOperation};
|
||||
use storage_traits::indexeddb::{BackendResult, IndexedDBThreadMsg, SyncOperation};
|
||||
use stylo_atoms::Atom;
|
||||
|
||||
use crate::dom::bindings::codegen::Bindings::IDBOpenDBRequestBinding::IDBOpenDBRequestMethods;
|
||||
|
||||
@@ -13,7 +13,7 @@ use js::rust::HandleValue;
|
||||
use profile_traits::ipc::IpcReceiver;
|
||||
use script_bindings::conversions::SafeToJSValConvertible;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use storage_traits::indexeddb_thread::{
|
||||
use storage_traits::indexeddb::{
|
||||
AsyncOperation, AsyncReadOnlyOperation, BackendError, BackendResult, IndexedDBKeyType,
|
||||
IndexedDBRecord, IndexedDBThreadMsg, IndexedDBTxnMode, PutItemResult,
|
||||
};
|
||||
@@ -37,7 +37,7 @@ use crate::dom::indexeddb::idbcursor::{IterationParam, iterate_cursor};
|
||||
use crate::dom::indexeddb::idbcursorwithvalue::IDBCursorWithValue;
|
||||
use crate::dom::indexeddb::idbobjectstore::IDBObjectStore;
|
||||
use crate::dom::indexeddb::idbtransaction::IDBTransaction;
|
||||
use crate::indexed_db::key_type_to_jsval;
|
||||
use crate::indexeddb::key_type_to_jsval;
|
||||
use crate::realms::enter_realm;
|
||||
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use dom_struct::dom_struct;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use profile_traits::ipc;
|
||||
use script_bindings::codegen::GenericUnionTypes::StringOrStringSequence;
|
||||
use storage_traits::indexeddb_thread::{IndexedDBThreadMsg, KeyPath, SyncOperation};
|
||||
use storage_traits::indexeddb::{IndexedDBThreadMsg, KeyPath, SyncOperation};
|
||||
use stylo_atoms::Atom;
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
|
||||
@@ -154,7 +154,7 @@ use crate::dom::hashchangeevent::HashChangeEvent;
|
||||
use crate::dom::history::History;
|
||||
use crate::dom::html::htmlcollection::{CollectionFilter, HTMLCollection};
|
||||
use crate::dom::html::htmliframeelement::HTMLIFrameElement;
|
||||
use crate::dom::indexeddb::idbfactory::IDBFactory;
|
||||
use crate::dom::idbfactory::IDBFactory;
|
||||
use crate::dom::inputevent::HitTestResult;
|
||||
use crate::dom::location::Location;
|
||||
use crate::dom::medialist::MediaList;
|
||||
|
||||
@@ -67,7 +67,7 @@ use crate::dom::dedicatedworkerglobalscope::{
|
||||
};
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::htmlscriptelement::{SCRIPT_JS_MIMES, ScriptOrigin, ScriptType};
|
||||
use crate::dom::indexeddb::idbfactory::IDBFactory;
|
||||
use crate::dom::idbfactory::IDBFactory;
|
||||
use crate::dom::performance::performance::Performance;
|
||||
use crate::dom::performance::performanceresourcetiming::InitiatorType;
|
||||
use crate::dom::promise::Promise;
|
||||
|
||||
@@ -20,7 +20,7 @@ use profile_traits::ipc;
|
||||
use profile_traits::ipc::IpcReceiver;
|
||||
use script_bindings::script_runtime::CanGc;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use storage_traits::indexeddb_thread::{BackendResult, IndexedDBKeyRange, IndexedDBKeyType};
|
||||
use storage_traits::indexeddb::{BackendResult, IndexedDBKeyRange, IndexedDBKeyType};
|
||||
|
||||
use crate::dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::FileBinding::FileMethods;
|
||||
@@ -37,8 +37,8 @@ use crate::dom::bindings::utils::set_dictionary_property;
|
||||
use crate::dom::blob::Blob;
|
||||
use crate::dom::file::File;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::indexeddb::idbkeyrange::IDBKeyRange;
|
||||
use crate::dom::indexeddb::idbobjectstore::KeyPath;
|
||||
use crate::dom::idbkeyrange::IDBKeyRange;
|
||||
use crate::dom::idbobjectstore::KeyPath;
|
||||
|
||||
pub fn create_channel<T>(
|
||||
global: DomRoot<GlobalScope>,
|
||||
@@ -34,7 +34,7 @@ pub(crate) mod document_loader;
|
||||
mod dom;
|
||||
pub(crate) use dom::canvas_context;
|
||||
pub(crate) mod fetch;
|
||||
pub(crate) mod indexed_db;
|
||||
pub(crate) mod indexeddb;
|
||||
mod init;
|
||||
mod layout_image;
|
||||
|
||||
|
||||
12
components/shared/storage/client_storage.rs
Normal file
12
components/shared/storage/client_storage.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use base::generic_channel::GenericSender;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum ClientStorageThreadMessage {
|
||||
/// Send a reply when done cleaning up thread resources and then shut it down
|
||||
Exit(GenericSender<()>),
|
||||
}
|
||||
@@ -8,30 +8,45 @@ use ipc_channel::ipc::{IpcError, IpcSender};
|
||||
use malloc_size_of::malloc_size_of_is_0;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::indexeddb_thread::IndexedDBThreadMsg;
|
||||
use crate::client_storage::ClientStorageThreadMessage;
|
||||
use crate::indexeddb::IndexedDBThreadMsg;
|
||||
use crate::webstorage_thread::WebStorageThreadMsg;
|
||||
|
||||
pub mod indexeddb_thread;
|
||||
pub mod client_storage;
|
||||
pub mod indexeddb;
|
||||
pub mod webstorage_thread;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct StorageThreads {
|
||||
web_storage_thread: GenericSender<WebStorageThreadMsg>,
|
||||
client_storage_thread: GenericSender<ClientStorageThreadMessage>,
|
||||
idb_thread: IpcSender<IndexedDBThreadMsg>,
|
||||
web_storage_thread: GenericSender<WebStorageThreadMsg>,
|
||||
}
|
||||
|
||||
impl StorageThreads {
|
||||
pub fn new(
|
||||
web_storage_thread: GenericSender<WebStorageThreadMsg>,
|
||||
client_storage_thread: GenericSender<ClientStorageThreadMessage>,
|
||||
idb_thread: IpcSender<IndexedDBThreadMsg>,
|
||||
web_storage_thread: GenericSender<WebStorageThreadMsg>,
|
||||
) -> StorageThreads {
|
||||
StorageThreads {
|
||||
web_storage_thread,
|
||||
client_storage_thread,
|
||||
idb_thread,
|
||||
web_storage_thread,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericSend<ClientStorageThreadMessage> for StorageThreads {
|
||||
fn send(&self, msg: ClientStorageThreadMessage) -> SendResult {
|
||||
self.client_storage_thread.send(msg)
|
||||
}
|
||||
|
||||
fn sender(&self) -> GenericSender<ClientStorageThreadMessage> {
|
||||
self.client_storage_thread.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl IpcSend<IndexedDBThreadMsg> for StorageThreads {
|
||||
fn send(&self, msg: IndexedDBThreadMsg) -> IpcSendResult {
|
||||
self.idb_thread.send(msg).map_err(IpcError::Bincode)
|
||||
|
||||
66
components/storage/client_storage.rs
Normal file
66
components/storage/client_storage.rs
Normal file
@@ -0,0 +1,66 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::thread;
|
||||
|
||||
use base::generic_channel::{self, GenericReceiver, GenericSender};
|
||||
use storage_traits::client_storage::ClientStorageThreadMessage;
|
||||
|
||||
pub trait ClientStorageThreadFactory {
|
||||
fn new(config_dir: Option<PathBuf>) -> Self;
|
||||
}
|
||||
|
||||
impl ClientStorageThreadFactory for GenericSender<ClientStorageThreadMessage> {
|
||||
fn new(config_dir: Option<PathBuf>) -> GenericSender<ClientStorageThreadMessage> {
|
||||
let (generic_sender, generic_receiver) = generic_channel::channel().unwrap();
|
||||
|
||||
let generic_sender_clone = generic_sender.clone();
|
||||
|
||||
thread::Builder::new()
|
||||
.name("ClientStorageThread".to_owned())
|
||||
.spawn(move || {
|
||||
ClientStorageThread::new(config_dir, generic_sender, generic_receiver).start();
|
||||
})
|
||||
.expect("Thread spawning failed");
|
||||
|
||||
generic_sender_clone
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClientStorageThread {
|
||||
_base_dir: PathBuf,
|
||||
_generic_sender: GenericSender<ClientStorageThreadMessage>,
|
||||
generic_receiver: GenericReceiver<ClientStorageThreadMessage>,
|
||||
}
|
||||
|
||||
impl ClientStorageThread {
|
||||
pub fn new(
|
||||
config_dir: Option<PathBuf>,
|
||||
generic_sender: GenericSender<ClientStorageThreadMessage>,
|
||||
generic_receiver: GenericReceiver<ClientStorageThreadMessage>,
|
||||
) -> ClientStorageThread {
|
||||
let base_dir = config_dir
|
||||
.unwrap_or_else(|| PathBuf::from("."))
|
||||
.join("clientstorage");
|
||||
|
||||
ClientStorageThread {
|
||||
_base_dir: base_dir,
|
||||
_generic_sender: generic_sender,
|
||||
generic_receiver,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&mut self) {
|
||||
#[allow(clippy::never_loop)]
|
||||
loop {
|
||||
match self.generic_receiver.recv().unwrap() {
|
||||
ClientStorageThreadMessage::Exit(sender) => {
|
||||
let _ = sender.send(());
|
||||
return;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,7 @@
|
||||
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use storage_traits::indexeddb_thread::{
|
||||
AsyncOperation, CreateObjectResult, IndexedDBTxnMode, KeyPath,
|
||||
};
|
||||
use storage_traits::indexeddb::{AsyncOperation, CreateObjectResult, IndexedDBTxnMode, KeyPath};
|
||||
use tokio::sync::oneshot;
|
||||
|
||||
pub use self::sqlite::SqliteEngine;
|
||||
|
||||
@@ -11,7 +11,7 @@ use rusqlite::{Connection, Error, OptionalExtension, params};
|
||||
use sea_query::{Condition, Expr, ExprTrait, IntoCondition, SqliteQueryBuilder};
|
||||
use sea_query_rusqlite::RusqliteBinder;
|
||||
use serde::Serialize;
|
||||
use storage_traits::indexeddb_thread::{
|
||||
use storage_traits::indexeddb::{
|
||||
AsyncOperation, AsyncReadOnlyOperation, AsyncReadWriteOperation, BackendError, BackendResult,
|
||||
CreateObjectResult, IndexedDBKeyRange, IndexedDBKeyType, IndexedDBRecord, IndexedDBTxnMode,
|
||||
KeyPath, PutItemResult,
|
||||
@@ -672,7 +672,7 @@ mod tests {
|
||||
use base::threadpool::ThreadPool;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use servo_url::ImmutableOrigin;
|
||||
use storage_traits::indexeddb_thread::{
|
||||
use storage_traits::indexeddb::{
|
||||
AsyncOperation, AsyncReadOnlyOperation, AsyncReadWriteOperation, CreateObjectResult,
|
||||
IndexedDBKeyRange, IndexedDBKeyType, IndexedDBTxnMode, KeyPath, PutItemResult,
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@ use log::{debug, warn};
|
||||
use rustc_hash::FxHashMap;
|
||||
use servo_config::pref;
|
||||
use servo_url::origin::ImmutableOrigin;
|
||||
use storage_traits::indexeddb_thread::{
|
||||
use storage_traits::indexeddb::{
|
||||
AsyncOperation, BackendError, BackendResult, CreateObjectResult, DbResult, IndexedDBThreadMsg,
|
||||
IndexedDBTxnMode, KeyPath, SyncOperation,
|
||||
};
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
pub mod client_storage;
|
||||
mod indexeddb;
|
||||
pub(crate) mod shared;
|
||||
mod storage_thread;
|
||||
mod webstorage;
|
||||
|
||||
pub use client_storage::ClientStorageThreadFactory;
|
||||
pub(crate) use indexeddb::IndexedDBThreadFactory;
|
||||
pub use storage_thread::new_storage_threads;
|
||||
pub(crate) use webstorage::WebStorageThreadFactory;
|
||||
|
||||
@@ -8,21 +8,24 @@ use base::generic_channel::GenericSender;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
||||
use storage_traits::StorageThreads;
|
||||
use storage_traits::indexeddb_thread::IndexedDBThreadMsg;
|
||||
use storage_traits::client_storage::ClientStorageThreadMessage;
|
||||
use storage_traits::indexeddb::IndexedDBThreadMsg;
|
||||
use storage_traits::webstorage_thread::WebStorageThreadMsg;
|
||||
|
||||
use crate::{IndexedDBThreadFactory, WebStorageThreadFactory};
|
||||
use crate::{ClientStorageThreadFactory, IndexedDBThreadFactory, WebStorageThreadFactory};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new_storage_threads(
|
||||
mem_profiler_chan: MemProfilerChan,
|
||||
config_dir: Option<PathBuf>,
|
||||
) -> (StorageThreads, StorageThreads) {
|
||||
let client_storage: GenericSender<ClientStorageThreadMessage> =
|
||||
ClientStorageThreadFactory::new(config_dir.clone());
|
||||
let idb: IpcSender<IndexedDBThreadMsg> = IndexedDBThreadFactory::new(config_dir.clone());
|
||||
let web_storage: GenericSender<WebStorageThreadMsg> =
|
||||
WebStorageThreadFactory::new(config_dir, mem_profiler_chan);
|
||||
(
|
||||
StorageThreads::new(web_storage.clone(), idb.clone()),
|
||||
StorageThreads::new(web_storage, idb),
|
||||
StorageThreads::new(client_storage.clone(), idb.clone(), web_storage.clone()),
|
||||
StorageThreads::new(client_storage, idb, web_storage),
|
||||
)
|
||||
}
|
||||
|
||||
22
components/storage/tests/client_storage.rs
Normal file
22
components/storage/tests/client_storage.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use base::generic_channel::{self, GenericSender};
|
||||
use storage::ClientStorageThreadFactory;
|
||||
use storage_traits::client_storage::ClientStorageThreadMessage;
|
||||
|
||||
#[test]
|
||||
fn test_exit() {
|
||||
let thread: GenericSender<ClientStorageThreadMessage> = ClientStorageThreadFactory::new(None);
|
||||
|
||||
let (sender, receiver) = generic_channel::channel().unwrap();
|
||||
thread
|
||||
.send(ClientStorageThreadMessage::Exit(sender))
|
||||
.unwrap();
|
||||
receiver.recv().unwrap();
|
||||
|
||||
// Workaround for https://github.com/servo/servo/issues/32912
|
||||
#[cfg(windows)]
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
}
|
||||
@@ -2,4 +2,5 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
mod client_storage;
|
||||
mod webstorage;
|
||||
|
||||
@@ -233,6 +233,7 @@ class MachCommands(CommandBase):
|
||||
"servoshell",
|
||||
"servo_url",
|
||||
"storage",
|
||||
"storage_traits",
|
||||
"xpath",
|
||||
]
|
||||
if not packages:
|
||||
|
||||
Reference in New Issue
Block a user