غالبًا ما يتم استدعاء الوظيفة cf_handle
كثيرًا ويتطلب تنفيذها الحصول على قفل قراءة للخريطة الأساسية. إذا تم استدعاء هذا في مسار سريع ، يمكن أن يكون له آثار على الأداء. يجب أن نحقق في تحويل هذا إلى نهج لا يتطلب قفلًا. على سبيل المثال ، يمكننا أن نجعل create_cf
و drop_cf
وأي وظيفة أخرى تغير الخريطة الداخلية تتطلب مرجعًا متغيرًا إلى DB
وتجعل المتصل مسؤولاً عن الحصول على أي أقفال بالترتيب لتغيير DB
.
مثله؟
use std::collections::HashMap;
#[derive(Debug)]
struct ColumnFamily(i32);
struct DB {
cfs:HashMap<i32,ColumnFamily>,
}
impl DB {
fn new()->DB{
let mut cfs = HashMap::new();
cfs.insert(1,ColumnFamily(1));
cfs.insert(2,ColumnFamily(2));
DB{
cfs
}
}
fn get(&self,key:i32)->&ColumnFamily{
self.cfs.get(&key).unwrap()
}
fn drop_key(&mut self,key:i32){
self.cfs.remove(&key);
}
}
fn main() {
let mut f = DB::new();
let a = f.get(1);
println!("{:?}",a);
f.drop_key(1);
let c = f.get(2);
println!("{:?}",c);
}
FWIW ، في مفترق paritech cf_handle
هو Copy
، وهو ليس آمنًا من الناحية الفنية (قد يقول OTOH أنه من الصعب إساءة الاستخدام) ، لكنه يتجنب استخدام الأقفال.
hjiayz نعم ، مشابه جدًا لذلك.
عندما حاولت إجراء هذا التغيير (على سبيل المثال ، خذ &mut self
عند إنشاء / حذف عائلات الأعمدة) واجهت مشاكل مع طريقة تعريف ColumnFamily
. سيخزن مرجعًا متغيرًا في PhantomData
مما يجعل الكود مثل هذا يفشل:
#[test]
fn property_cf_test() {
let n = DBPath::new("_rust_rocksdb_property_cf_test");
{
let opts = Options::default();
let mut db = DB::open_default(&n).unwrap(); // Notice the `mut`
let cf = db.create_cf("cf1", &opts).unwrap();
let value = db.property_value_cf(cf, "rocksdb.stats").unwrap().unwrap();
assert!(value.contains("Stats"));
}
}
يحدث الخطأ عند إجراء استدعاء طريقة على db يأخذ &self
، مثل db.property_value_cf()
ويمرر ColumnFamily
(الذي يخزن &mut
في db
field):
error[E0502]: cannot borrow `db` as immutable because it is also borrowed as mutable
--> tests/test_property.rs:39:21
|
38 | let cf = db.create_cf("cf1", &opts).unwrap();
| -- mutable borrow occurs here
39 | let value = db.property_value_cf(cf, "rocksdb.stats").unwrap().unwrap();
| ^^ -- mutable borrow later used here
| |
| immutable borrow occurs here
لا يمكنني التفكير في طريقة أنيقة للغاية للتغلب على هذا ، ولكن أحد الخيارات هو عدم إرجاع ColumnFamily
من create_cf
وبدلاً من ذلك السماح باستهلاك الكود بجلبه بمكالمة إلى cf_handle()
:
#[test]
fn property_cf_test() {
let n = DBPath::new("_rust_rocksdb_property_cf_test");
{
let opts = Options::default();
let mut db = DB::open_default(&n).unwrap();
db.create_cf("cf1", &opts).unwrap();
let cf = db.cf_handle("cf1").unwrap(); // Get the CF
let value = db.property_value_cf(cf, "rocksdb.stats").unwrap().unwrap();
assert!(value.contains("Stats"));
}
}
هل تغيير create_cf()
لإرجاع Result<(), Error>
تغيير مقبول؟
dvdplm أصبحت إضافة الأعمار إلى ColumnFamily
بمثابة كابوس من منظور مريح. أرغب في اتباع نهج لا يحتاج إلى مدى الحياة ولكنه أيضًا لا يخاطر باستخدام مؤشر عائلة العمود بعد حذفه. من المحتمل أن يؤثر هذا التغيير على كيفية قيامنا بإزالة الأقفال من cf_handle
- ربما لن ترى هذه المشكلة.
أتفق مع iSynaptic. من الواضح أن إعادة الإشارة إلى ColumnFamily
هي طريقة آمنة فقط في هذه الحالة.
ربما يمكن دمج # 298 إذن؟
هل حلها رقم 314؟ أي خطط للإفراج إذا كان الأمر كذلك؟
نعم إنه كذلك. نحن نخطط لإصداره في المستقبل القريب.
aleksuss ما هي حالة الإفراج عنه؟ :)
bkchr أعتقد أننا سنفعل ذلك الأسبوع المقبل.
التعليق الأكثر فائدة
نعم إنه كذلك. نحن نخطط لإصداره في المستقبل القريب.