github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/validator/src/database/lmdb_ffi.rs (about)

     1  /*
     2   * Copyright 2018 Intel Corporation
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   * ------------------------------------------------------------------------------
    16   */
    17  use cpython::{PyList, PyObject, Python};
    18  use database::lmdb::*;
    19  use py_ffi;
    20  use std::ffi::CStr;
    21  use std::os::raw::{c_char, c_void};
    22  use std::path::Path;
    23  
    24  #[repr(u32)]
    25  #[derive(Debug)]
    26  pub enum ErrorCode {
    27      Success = 0,
    28      NullPointerProvided = 0x01,
    29      InvalidFilePath = 0x02,
    30      InvalidIndexString = 0x03,
    31  
    32      InitializeContextError = 0x11,
    33      InitializeDatabaseError = 0x12,
    34  }
    35  
    36  #[no_mangle]
    37  pub extern "C" fn lmdb_database_new(
    38      path: *const c_char,
    39      file_size: usize,
    40      indexes_ptr: *mut py_ffi::PyObject,
    41      db_ptr: *mut *const c_void,
    42  ) -> ErrorCode {
    43      if path.is_null() {
    44          return ErrorCode::NullPointerProvided;
    45      }
    46  
    47      let indexes: Vec<String> = unsafe {
    48          let py = Python::assume_gil_acquired();
    49          let py_obj = PyObject::from_borrowed_ptr(py, indexes_ptr);
    50          let py_list: PyList = py_obj.extract(py).unwrap();
    51          py_list
    52              .iter(py)
    53              .map(|pyobj| pyobj.extract::<String>(py).unwrap())
    54              .collect()
    55      };
    56  
    57      let db_path = unsafe {
    58          match CStr::from_ptr(path).to_str() {
    59              Ok(s) => s,
    60              Err(_) => return ErrorCode::InvalidFilePath,
    61          }
    62      };
    63  
    64      let ctx = match LmdbContext::new(Path::new(&db_path), indexes.len(), Some(file_size)) {
    65          Ok(ctx) => ctx,
    66          Err(err) => {
    67              error!(
    68                  "Unable to create LMDB context for db at {}: {:?}",
    69                  db_path, err
    70              );
    71              return ErrorCode::InitializeContextError;
    72          }
    73      };
    74  
    75      match LmdbDatabase::new(ctx, &indexes) {
    76          Ok(db) => {
    77              unsafe {
    78                  *db_ptr = Box::into_raw(Box::new(db)) as *const c_void;
    79              }
    80              ErrorCode::Success
    81          }
    82          Err(err) => {
    83              error!("Unable to create Database at {}: {:?}", db_path, err);
    84              ErrorCode::InitializeDatabaseError
    85          }
    86      }
    87  }
    88  
    89  #[no_mangle]
    90  pub extern "C" fn lmdb_database_drop(lmdb_database: *mut c_void) -> ErrorCode {
    91      if lmdb_database.is_null() {
    92          return ErrorCode::NullPointerProvided;
    93      }
    94  
    95      unsafe { Box::from_raw(lmdb_database as *mut LmdbDatabase) };
    96      ErrorCode::Success
    97  }