Skip to content

Commit 440c9f3

Browse files
committed
Improved memory handling in plugged wallet
Signed-off-by: Darko Kulic <[email protected]>
1 parent 76559bf commit 440c9f3

File tree

1 file changed

+118
-37
lines changed
  • libindy/src/services/wallet/storage/plugged

1 file changed

+118
-37
lines changed

libindy/src/services/wallet/storage/plugged/mod.rs

Lines changed: 118 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,75 @@ pub struct PluggedWalletJSONValues {
3535

3636
impl<'a> JsonDecodable<'a> for PluggedWalletJSONValues {}
3737

38+
39+
// This struct is used as a helper to free the resource even in case of error.
40+
// It is workaround for Rust's lack of try/catch.
41+
struct ResourceGuard {
42+
storage_handle: i32,
43+
item_handle: i32,
44+
free_handler: extern fn(storage_handle: i32, item_handle: i32) -> ErrorCode
45+
}
46+
47+
impl ResourceGuard {
48+
fn new(storage_handle: i32,
49+
item_handle: i32,
50+
free_handler: extern fn(s_handle: i32, i_handle: i32) -> ErrorCode
51+
) -> Self {
52+
Self {
53+
storage_handle,
54+
item_handle,
55+
free_handler
56+
}
57+
}
58+
}
59+
60+
impl Drop for ResourceGuard {
61+
fn drop(&mut self) {
62+
(self.free_handler)(self.storage_handle, self.item_handle);
63+
}
64+
}
65+
66+
3867
#[derive(PartialEq, Debug)]
3968
struct PluggedStorageIterator {
40-
storage: PluggedStorage,
69+
storage_handle: i32,
4170
search_handle: i32,
4271
options: SearchOptions,
72+
fetch_search_next_record_handler: WalletFetchSearchNextRecord,
73+
get_search_total_count_handler: WalletGetSearchTotalCount,
74+
get_record_type_handler: WalletGetRecordType,
75+
get_record_id_handler: WalletGetRecordId,
76+
get_record_value_handler: WalletGetRecordValue,
77+
get_record_tags_handler: WalletGetRecordTags,
78+
free_record_handler: WalletFreeRecord,
79+
free_search_handler: WalletFreeSearch,
80+
}
81+
82+
impl PluggedStorageIterator {
83+
fn new(storage: &PluggedStorage, search_handle: i32, options: SearchOptions) -> Self {
84+
Self {
85+
storage_handle: storage.handle,
86+
search_handle: search_handle,
87+
options: options,
88+
fetch_search_next_record_handler: storage.fetch_search_next_record_handler,
89+
get_search_total_count_handler: storage.get_search_total_count_handler,
90+
get_record_type_handler: storage.get_record_type_handler,
91+
get_record_id_handler: storage.get_record_id_handler,
92+
get_record_value_handler: storage.get_record_value_handler,
93+
get_record_tags_handler: storage.get_record_tags_handler,
94+
free_record_handler: storage.free_record_handler,
95+
free_search_handler: storage.free_search_handler,
96+
}
97+
}
4398
}
4499

45100
impl StorageIterator for PluggedStorageIterator {
46101
fn next(&mut self) -> Result<Option<StorageEntity>, WalletStorageError> {
47102
let mut record_handle = -1;
48103

49-
let err = (self.storage.fetch_search_next_record_handler)(self.storage.handle,
50-
self.search_handle,
51-
&mut record_handle);
104+
let err = (self.fetch_search_next_record_handler)(self.storage_handle,
105+
self.search_handle,
106+
&mut record_handle);
52107

53108
if err == ErrorCode::WalletItemNotFound {
54109
return Ok(None);
@@ -57,12 +112,18 @@ impl StorageIterator for PluggedStorageIterator {
57112
return Err(WalletStorageError::PluggedStorageError(err));
58113
}
59114

115+
let record_free_helper = ResourceGuard {
116+
storage_handle: self.storage_handle,
117+
item_handle: record_handle,
118+
free_handler: self.free_record_handler
119+
};
120+
60121
let type_ = if self.options.retrieve_type.unwrap_or(false) {
61122
let mut type_ptr: *const c_char = ptr::null_mut();
62123

63-
let err = (self.storage.get_record_type_handler)(self.storage.handle,
64-
record_handle,
65-
&mut type_ptr);
124+
let err = (self.get_record_type_handler)(self.storage_handle,
125+
record_handle,
126+
&mut type_ptr);
66127

67128
if err != ErrorCode::Success {
68129
return Err(WalletStorageError::PluggedStorageError(err));
@@ -74,9 +135,9 @@ impl StorageIterator for PluggedStorageIterator {
74135
let id = {
75136
let mut id_ptr: *const c_char = ptr::null_mut();
76137

77-
let err = (self.storage.get_record_id_handler)(self.storage.handle,
78-
record_handle,
79-
&mut id_ptr);
138+
let err = (self.get_record_id_handler)(self.storage_handle,
139+
record_handle,
140+
&mut id_ptr);
80141

81142
if err != ErrorCode::Success {
82143
return Err(WalletStorageError::PluggedStorageError(err));
@@ -87,10 +148,10 @@ impl StorageIterator for PluggedStorageIterator {
87148
let value = if self.options.retrieve_value.unwrap_or(true) {
88149
let mut value_bytes: *const u8 = ptr::null();
89150
let mut value_bytes_len: usize = 0;
90-
let err = (self.storage.get_record_value_handler)(self.storage.handle,
91-
record_handle,
92-
&mut value_bytes,
93-
&mut value_bytes_len);
151+
let err = (self.get_record_value_handler)(self.storage_handle,
152+
record_handle,
153+
&mut value_bytes,
154+
&mut value_bytes_len);
94155

95156
if err != ErrorCode::Success {
96157
return Err(WalletStorageError::PluggedStorageError(err));
@@ -102,9 +163,9 @@ impl StorageIterator for PluggedStorageIterator {
102163

103164
let tags = if self.options.retrieve_tags.unwrap_or(false) {
104165
let mut tags_ptr: *const c_char = ptr::null_mut();
105-
let err = (self.storage.get_record_tags_handler)(self.storage.handle,
106-
record_handle,
107-
&mut tags_ptr);
166+
let err = (self.get_record_tags_handler)(self.storage_handle,
167+
record_handle,
168+
&mut tags_ptr);
108169

109170
if err != ErrorCode::Success {
110171
return Err(WalletStorageError::PluggedStorageError(err));
@@ -114,8 +175,6 @@ impl StorageIterator for PluggedStorageIterator {
114175
Some(_tags_from_json(tags_json)?)
115176
} else {None};
116177

117-
(self.storage.free_record_handler)(self.storage.handle, record_handle);
118-
119178
Ok(Some(StorageEntity{
120179
type_: type_,
121180
name: id,
@@ -128,9 +187,9 @@ impl StorageIterator for PluggedStorageIterator {
128187
let mut total_count = 0;
129188

130189
if self.options.retrieve_total_count.unwrap_or(false) {
131-
let err = (self.storage.get_search_total_count_handler)(self.storage.handle,
132-
self.search_handle,
133-
&mut total_count);
190+
let err = (self.get_search_total_count_handler)(self.storage_handle,
191+
self.search_handle,
192+
&mut total_count);
134193

135194
if err != ErrorCode::Success {
136195
return Err(WalletStorageError::PluggedStorageError(err));
@@ -146,11 +205,11 @@ impl StorageIterator for PluggedStorageIterator {
146205

147206
impl Drop for PluggedStorageIterator {
148207
fn drop(&mut self) {
149-
(self.storage.free_search_handler)(self.storage.handle, self.search_handle);
208+
(self.free_search_handler)(self.storage_handle, self.search_handle);
150209
}
151210
}
152211

153-
#[derive(PartialEq, Debug, Clone)]
212+
#[derive(PartialEq, Debug)]
154213
struct PluggedStorage {
155214
handle: i32,
156215
add_record_handler: WalletAddRecord,
@@ -306,6 +365,12 @@ impl WalletStorage for PluggedStorage {
306365
return Err(WalletStorageError::PluggedStorageError(err));
307366
}
308367

368+
let record_free_helper = ResourceGuard {
369+
storage_handle: self.handle,
370+
item_handle: record_handle,
371+
free_handler: self.free_record_handler
372+
};
373+
309374
let value = if options.retrieve_value {
310375
let mut value_bytes: *const u8 = ptr::null();
311376
let mut value_bytes_len: usize = 0;
@@ -343,8 +408,6 @@ impl WalletStorage for PluggedStorage {
343408
tags
344409
};
345410

346-
let err = (self.free_record_handler)(self.handle, record_handle);
347-
348411
if err != ErrorCode::Success {
349412
return Err(WalletStorageError::PluggedStorageError(err));
350413
}
@@ -471,12 +534,16 @@ impl WalletStorage for PluggedStorage {
471534
return Err(WalletStorageError::PluggedStorageError(err));
472535
}
473536

537+
let metadata_free_helper = ResourceGuard {
538+
storage_handle: self.handle,
539+
item_handle: metadata_handle,
540+
free_handler: self.free_storage_metadata_handler
541+
};
542+
474543
let metadata = base64::decode(
475544
unsafe { CStr::from_ptr(metadata_ptr).to_str()? }
476545
)?;
477546

478-
(self.free_storage_metadata_handler)(self.handle, metadata_handle);
479-
480547
Ok(metadata)
481548
}
482549

@@ -502,17 +569,17 @@ impl WalletStorage for PluggedStorage {
502569
}
503570

504571
Ok(Box::new(
505-
PluggedStorageIterator {
506-
storage: self.clone() /* TODO avoid clone. Use Rc or better approach. */,
572+
PluggedStorageIterator::new(
573+
&self,
507574
search_handle,
508-
options: SearchOptions {
575+
SearchOptions {
509576
retrieve_records: Some(true),
510577
retrieve_total_count: Some(false),
511578
retrieve_type: Some(true),
512579
retrieve_value: Some(true),
513580
retrieve_tags: Some(true),
514581
}
515-
}
582+
)
516583
))
517584
}
518585

@@ -533,11 +600,13 @@ impl WalletStorage for PluggedStorage {
533600
return Err(WalletStorageError::PluggedStorageError(err));
534601
}
535602

536-
Ok(Box::new(PluggedStorageIterator {
537-
storage: self.clone() /* TODO avoid clone. Use Rc or better approach. */,
538-
search_handle,
539-
options
540-
}))
603+
Ok(Box::new(
604+
PluggedStorageIterator::new(
605+
&self,
606+
search_handle,
607+
options
608+
)
609+
))
541610
}
542611

543612
fn close(&mut self) -> Result<(), WalletStorageError> {
@@ -547,10 +616,22 @@ impl WalletStorage for PluggedStorage {
547616
return Err(WalletStorageError::PluggedStorageError(err));
548617
}
549618

619+
// invalidate the handle, just in case.
620+
self.handle = -1;
621+
550622
Ok(())
551623
}
552624
}
553625

626+
impl Drop for PluggedStorage {
627+
fn drop(&mut self) {
628+
// if storage is not closed, close it before drop.
629+
if self.handle >= 0 {
630+
self.close();
631+
}
632+
}
633+
}
634+
554635
#[derive(Debug)]
555636
pub struct PluggedStorageType {
556637
create_handler: WalletCreate,

0 commit comments

Comments
 (0)