This code:
#[macro_use]
extern crate lazy_static;
extern crate mysql;
use mysql::*;
fn some_fn() {
lazy_static! {
static ref CONNECTION: Conn = Conn::new("mysql://root:password#127.0.0.1:3306/mydb?prefer_socket=false").unwrap();
}
}
generates a very long error message:
error[E0277]: the trait bound `*mut std::os::raw::c_void: std::marker::Sync` is not satisfied in `winapi::minwinbase::OVERLAPPED`
--> src\main.rs:8:5
|
8 | / lazy_static! {
9 | | static ref CONNECTION: Conn = Conn::new("mysql://root:password#127.0.0.1:3306/mydb?prefer_socket=false").unwrap();
10 | | }
| |_____^ `*mut std::os::raw::c_void` cannot be shared between threads safely
|
= help: within `winapi::minwinbase::OVERLAPPED`, the trait `std::marker::Sync` is not implemented for `*mut std::os::raw::c_void`
= note: required because it appears within the type `winapi::minwinbase::OVERLAPPED`
= note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<winapi::minwinbase::OVERLAPPED>`
= note: required because it appears within the type `std::boxed::Box<winapi::minwinbase::OVERLAPPED>`
= note: required because it appears within the type `named_pipe::Overlapped`
= note: required because it appears within the type `named_pipe::PipeClient`
= note: required because it appears within the type `std::option::Option<named_pipe::PipeClient>`
= note: required because it appears within the type `std::io::BufWriter<named_pipe::PipeClient>`
= note: required because it appears within the type `std::option::Option<std::io::BufWriter<named_pipe::PipeClient>>`
= note: required because it appears within the type `bufstream::InternalBufWriter<named_pipe::PipeClient>`
= note: required because it appears within the type `std::io::BufReader<bufstream::InternalBufWriter<named_pipe::PipeClient>>`
= note: required because it appears within the type `bufstream::BufStream<named_pipe::PipeClient>`
= note: required because it appears within the type `mysql::io::Stream`
= note: required because it appears within the type `std::option::Option<mysql::io::Stream>`
= note: required because it appears within the type `mysql::Conn`
= note: required by `lazy_static::lazy::Lazy`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
Is it because mysql::Conn is not intended to use in multithreaded apps?
How I can use lazy_static if my program is not multithreaded and I use non-thread-safe types?
Your code works just fine... on macOS. I believe this to be a bug with the
implementation of the MySQL crate, and the author agreed, fixing the bug in less than a day. You should be able to just upgrade the crate and use your original code.
As a temporary workaround, you can wrap the Conn in a Mutex:
use mysql::*;
use std::sync::Mutex;
fn some_fn() {
lazy_static! {
static ref CONNECTION: Mutex<Conn> = Mutex::new(Conn::new("mysql://root:password#127.0.0.1:3306/mydb?prefer_socket=false").unwrap());
}
}
if my program is not multithreaded and I use non-thread-safe types?
I always recommend against using global variables, threads or not. Instead, create your Conn at the top of your program and pass references to it into all of your functions.
Related
I was parsing some string input from a file when I came across this error. Normally it should not make a difference if you chain a series of methods on a single line or separate them into multiple operations. Yet here, it does not compile when the method chain is in a single line.
I do not get an error when split to multiple statements like so (link to playground)
let input = std::fs::read_to_string("tst_input.txt").expect("Failed to read input");
let input = input
.lines()
.map(|l| {
let mut iter = l.split(" | ");
(
iter.next()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>(),
iter.next()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>(),
)
})
.collect::<Vec<_>>();
I get a lifetime error when it is in a single statement like so (link to playground)
let input = std::fs::read_to_string("tst_input.txt")
.expect("Failed to read input")
.lines()
.map(|l| {
let mut iter = l.split(" | ");
(
iter.next()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>(),
iter.next()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>(),
)
})
.collect::<Vec<_>>()
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:2:17
|
2 | let input = std::fs::read_to_string("tst_input.txt")
| _________________^
3 | | .expect("Failed to read input")
| |_______________________________________^ creates a temporary which is freed while still in use
...
18 | .collect::<Vec<_>>();
| - temporary value is freed at the end of this statement
19 | println!("{:?}", input);
| ----- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
Should these 2 cases be effectively identical? why is the compiler treating them differently? Could this possibly be a compiler error?
These two cases are not identical, since the stored information differs.
In Rust, variables have semantic meaning: they act as a place where the information is stored, and, what's more important, they define when this information is destroyed - this is handled by Drop trait. By default, drop method is called for every variable which goes out of scope; this can be overridden with mem::forget and some other functions like Box::into_raw, but these are rather niche cases.
In the first case, the data being read is stored into the input variable of type String. This type wraps Vec<u8>, which implements Drop, so this data is deallocated when input goes out of scope. Then, the second input variable is of type Vec<(Vec<&str>, Vec<&str>)> - you can see that it contains a reference, so it is borrowing from the first input, so it must live no longer then the source string. Here, this is satisfied - of course, as long as you don't try to return this value up the stack, in which case the source string is dropped, and the references would dangle.
In the one-line version, however, the string is not stored anywhere - it is a temporary, which is destroyed right at the end of statement. That's why you're not allowed to hold any references to it. You can, however, make an owned version of the split data, by inserting an extra mapping operation:
let _: Vec<(Vec<String>, Vec<String>)> = std::fs::read_to_string("tst_input.txt")
.expect("Failed to read input")
// This iterator borrows from the temporary...
.lines()
.map(|l| {
// ...this iterator reborrows that borrow...
let mut iter = l.split(" | ");
(
iter.next()
.unwrap()
.split_whitespace()
// ...and this operation clones the source data,
// so they are copied to the new owned location,
// and not referenced anymore, so can be freely dropped
.map(str::to_owned)
.collect::<Vec<_>>(),
iter.next()
.unwrap()
.split_whitespace()
.map(str::to_owned)
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>();
A minimal recreation of the issue might help
let split_value = String::from("example")// <- string owned value
.split("x");
// string has no owner, so its lifetime ends
println!("{:?}", split_value); //error
A reference must not outlive the lifetime of the value it is referencing. Because the string is not being stored anywhere, and therefore has no owner, the value's lifetime ends.
And because split returns data that references that string value, its lifetime is linked to that string so it also ends.
By storing the result in a variable, the string now has a lifetime that lives past the expression.
let str_result = String::from("example"); //str_result owns the string value
let split_value = s.split("x");
println!("{:?}", r);
split_value can be printed because str_result's lifetime ends at the end of the function, therefore references to str_result are valid too.
I want to catch and handle SAPSQL_DATA_LOSS in my ABAP code.
I tried this:
try.
SELECT *
FROM (rtab_name) AS rtab
WHERE (sub_condition)
into table #<sub_result>
.
catch SAPSQL_DATA_LOSS into error.
...
endtry.
But above code is not valid. I get this message:
Type "SAPSQL_DATA_LOSS" is not valid
And I tried this:
catch SYSTEM-EXCEPTIONS SAPSQL_DATA_LOSS = 123.
SELECT *
...
.
endcatch.
if sy-subrc = 123.
...
endif.
But above code gives me:
Instead of "SAPSQL_DATA_LOSS" expected "system-exception" (translated from german to english by me)
How to catch SAPSQL_DATA_LOSS?
This question is not about "why does this exception happen?". This is already solved. My code should handle the exception.
SAPSQL_DATA_LOSS is a runtime error.
As SAPSQL_DATA_LOSS is not a class-based exception, it is not possible to catch it using try catch.
As SAPSQL_DATA_LOSS is not a catchable runtime error, it is not possible to catch it using try catch SYSTEM-EXCEPTIONS.
see the below catchable runtime errors.
https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abenueb-abfb-sysexc.htm
After some tries I can propose you a possible solution.
This is a workaround:
I don't know if it can be applied to your case, since it needs the select statement to be wrapped into an RFC function module !
The main point is that a short dump (message type X) CAN be handled in RFC calls.
So using an RFC (CALL FUNCTION 'xxxxx' destination 'NONE' for example) and using special exception SYSTEM_FAILURE, the system does not terminate the caller program, but instead it returns a SY-SUBRC > 0 with the Short dump informations in system message fields (SY-MSGxx).
STEPS
Create a Function module (RFC enabled) with your select statement input + the row type of the result table. (All parameters passed by value)
You need this last parameter since generic tables can't be passed in RFC (no "TYPE ANY TABLE" allowed)
FUNCTION Z_DYN_SEL .
*"----------------------------------------------------------------------
*"*"Local interface:
*" IMPORTING
*" VALUE(RTAB_NAME) TYPE TABNAME16
*" VALUE(SUB_CONDITION) TYPE STRING
*" VALUE(RESULT_TYPE) TYPE STRING
*"----------------------------------------------------------------------
* RTAB_NAME: DB Table
* SUB_CONDITION: WHERE Condition
* RESULT_TYPE: The ROW type of the internal table
field-symbols <sub_result> type any table.
* DEFINE LOCAL DYNAMIC TABLE TO STORE THE RESULT
data: lr_res type ref to data.
create data lr_res type standard table of (result_type).
assign lr_res->* to <sub_result>.
* DYNAMIC SELECT
select *
from (rtab_name) as rtab
where (sub_condition)
into table #<sub_result>.
* EXPORT RESULT TO A MEMORY ID, SO IT CAN BE RETRIEVED BY CALLER
export res = <sub_result> to memory id 'RES'.
Main program:
In this caller example some parameters are passed to the RFC.
KTOKD field (should be 4 chars long) is passed with a char10 value (producing your short dump).
If ANY Dump is triggered inside the function, we can now handle it.
If everything went fine, IMPORT result from the EXPORT statement inside the RFC
field-symbols <sub_result> type any table.
data: lr_res type ref to data.
create data lr_res type standard table of KNA1.
assign lr_res->* to <sub_result>.
data lv_msg type char255.
call function 'Z_DYN_SEL' destination 'NONE'
exporting
rtab_name = 'KNA1'
sub_condition = `KTOKD = 'D001xxxxxx'`
result_type = 'KNA1'
exceptions
system_failure = 1 message lv_msg.
if sy-subrc = 0.
import res = <sub_result> from memory id 'RES'.
else.
write: / lv_msg.
write : / sy-msgid, sy-msgno, sy-msgty, sy-msgv1, sy-msgv2, sy-msgv3, sy-msgv4.
endif.
RESULTS
After the RFC call in case of a short dump in the select statement, the program is not terminated and the following pieces of information are available
SY-SUBRC = 1
lv_msg is the error text (Data was lost while copying a value.)
Sy-msgid = 00
Sy-msgno = '341'
Sy-msgty = 'X'
Sy-msgv1 = 'SAPSQL_DATA_LOSS'
I have several custom exception classes that were created "With Message Class". Since I can't directly get a message from them, I want to create a utility method that returns a BAPIRET2 from a given exception based on the values in IF_T100_MESSAGE~T100KEY. However, I can't provide that method with a generic CX_ROOT importing parameter as this class is not message-enabled. I also can't create a generic message-enabled exception class as new classes have to inherit from one of CX_STATIC_CHECK, CX_DYNAMIC_CHECK, or CX_NOCHECK.
How can I then retrieve the message details from an unspecified exception? Should I create a method that receives a CX_ROOT and then does up to three calls to methods with an import typed to each of the three possible subclasses? Or are there better alternatives?
You could prepare a type descriptor of the interface (once):
DATA: lr_t100_descr TYPE REF TO cl_abap_intfdescr.
lr_t100_descr ?= cl_abap_typedescr=>describe_by_name( 'IF_T100_MESSAGE' ).
and then examine each exception as it comes your way:
DATA: lr_t100_exception TYPE REF TO if_t100_message.
IF lr_t100_descr->applies_to( ir_any_exception ) = abap_true.
lr_t100_exception ?= ir_any_exception.
" ...
ENDIF.
You could use the message collector object, so for example
DATA:
excp type ref to CX_ROOT,
bapi_messages type BAPIRETTAB,
message_collector type ref to IF_RECA_MESSAGE_LIST.
FIELD_SYMBOLS:
<bapi_message> TYPE BAPIRET2.
message_collector = cf_reca_message_list=>create( ).
TRY.
" some code which may cause and exception
CATCH cx_root into excp.
message_collector->add_from_exxeption( io_exception = excp).
ENDTRY.
bapi_messages = message_collector->get_list_as_bapiret( ).
LOOP AT bapi_messages ASSIGNING <bapi_message>.
" write out message
ENDLOOP.
It is well worth checking out the message collector object.
For example
http://wiki.scn.sap.com/wiki/display/profile/2007/07/09/Message+Handling+-+Finding+the+Needle+in+the+Haystack
For a logging class I use something like this:
METHOD add_message_exception.
DATA:
lr_type TYPE REF TO cl_abap_typedescr,
lr_class TYPE REF TO cl_abap_classdescr,
lr_intf TYPE REF TO cl_abap_intfdescr,
l_bapiret2 TYPE bapiret2,
lr_msg TYPE REF TO if_t100_message.
CHECK ir_exception IS NOT INITIAL.
l_bapiret2-type = i_type.
"Test for T100KEY interface
cl_abap_classdescr=>describe_by_object_ref(
EXPORTING
p_object_ref = ir_exception
RECEIVING
p_descr_ref = lr_type
EXCEPTIONS
reference_is_initial = 1
OTHERS = 2 ).
TRY.
lr_class ?= lr_type.
IF sy-subrc = 0.
lr_class->get_interface_type(
EXPORTING
p_name = 'IF_T100_MESSAGE'
RECEIVING
p_descr_ref = lr_intf
EXCEPTIONS
interface_not_found = 1
OTHERS = 2 ).
IF sy-subrc = 0.
lr_msg ?= ir_exception. "Cast to interface
l_bapiret2-id = lr_msg->t100key-msgid.
l_bapiret2-number = lr_msg->t100key-msgno.
cl_message_helper=>set_msg_vars_for_if_t100_msg( text = lr_msg ).
l_bapiret2-message_v1 = sy-msgv1.
l_bapiret2-message_v2 = sy-msgv2.
l_bapiret2-message_v3 = sy-msgv3.
l_bapiret2-message_v4 = sy-msgv4.
l_bapiret2-message = me->get_msg(
i_msgid = l_bapiret2-id
i_msgno = l_bapiret2-number ).
ENDIF.
ENDIF.
CATCH cx_root.
"Pokémon exception handling
ENDTRY.
"No T100KEY Interface available
IF lr_msg IS INITIAL.
l_bapiret2-message = ir_exception->if_message~get_text( ).
l_bapiret2-message_v1 = sy-msgv1.
l_bapiret2-message_v2 = sy-msgv2.
l_bapiret2-message_v3 = sy-msgv3.
l_bapiret2-message_v4 = sy-msgv4.
ENDIF.
ENDMETHOD.
Hope this helps as I struggled with the same problem. Maybe there is some adjustment needed, but I think you get the basic idea. This method can handle
I might be missing something, but can't you just use IF_MESSAGE~GET_TEXT which is present on CX_ROOT ?
Otherwise, I would make it the responsibility of the custom exception class to have a method that can return a proper message ( it might rely on the utility method you are planning on ).
I will run a set of experiments. The main method evaluated has the following signature:
[Model threshold] = detect(...
TrainNeg, TrainPos, nf, nT, factors, ...
removeEachStage, applyEstEachStage, removeFeatures);
where removeEachStage, applyEstEachStage, and removeFeatures are booleans. You can see that if I reverse the order of any of these boolean parameters I may get wrong results.
Is there a method in MATLAB that allows better organization in order to minimize this kind of error? Or is there any tool I can use to protect me against these errors?
Organization with a struct
You could input a struct that has these parameters as it's fields.
For example a structure with fields
setts.TrainNeg
.TrainPos
.nf
.nT
.factors
.removeEachStage
.applyEstEachStage
.removeFeatures
That way when you set the fields it is clear what the field is, unlike a function call where you have to remember the order of the parameters.
Then your function call becomes
[Model threshold] = detect(setts);
and your function definition would be something like
function [model, threshold] = detect(setts)
Then simply replace the occurrences of e.g. param with setts.param.
Mixed approach
You can also mix this approach with your current one if you prefer, e.g.
[Model threshold] = detect(in1, in2, setts);
if you wanted to still explicitly include in1 and in2, and bundle the rest into setts.
OOP approach
Another option is to turn detect into a class. The benefit to this is that a detect object would then have member variables with fixed names, as opposed to structs where if you make a typo when setting a field you just create a new field with the misspelled name.
For example
classdef detect()
properties
TrainNeg = [];
TrainPos = [];
nf = [];
nT = [];
factors = [];
removeEachStage = [];
applyEstEachStage = [];
removeFeatures =[];
end
methods
function run(self)
% Put the old detect code in here, use e.g. self.TrainNeg to access member variables (aka properties)
end
end
I'm using GUIDE to create an interface where a function [x,y]=function(a,b,c,d) will be executed when the button is clicked. Im having problems to get this to work. GUIDE creates an autogenerated function with the syntax varargout = LineasA(varargin).
I'm calling the GUI using this syntax [x,y]=LineasA(a,b,c,d).
Errors I get are:
Error in ==> LineasA>LineasA_OutputFcn at 73
varargout{1} = handles.output;
??? Error using ==> feval
Output argument "varargout{2}" (and maybe others) not assigned during call to
"C:\Users\ZeTa\Documents\MATLAB\ImagenB\LineasA.m>LineasA_OutputFcn".
Error in ==> gui_mainfcn at 263
[varargout{1:nargout}] = feval(gui_State.gui_OutputFcn, gui_hFigure, [],
gui_Handles);
Error in ==> LineasA at 40
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
Error in ==> ImagenB at 17
[MatrizB,Cuenta]=LineasA(Cuenta,waveformObj,channelObj,MatrizB);
You have to be clear where you are getting the inputs to this function, and where you want the outputs to go. It is proper coding to store the inputs and outputs in the handles struct that is passed into the callback. Also, the proper callback structure is:
LineasA(hObject, eventdata, handles)
However, if you insist on calling and storing from the base workspace, you can do as follows:
LineasA(hObject, eventdata, handles)
% grab values from base workspace
Cuenta = evalin('base', 'Cuenta');
waveformObj = evalin('base', 'waveformObj');
channelObj = evalin('base', 'channelObj');
MatrizB = evalin('base', 'MatrizB');
% the rest of your code
% assign outputs
assignin('base', 'MatrizB', matrizB);
assignin('base', 'Cuenta', Cuenta);
end
However I recommend getting those values in the handles structure and not to use evalin and assignin, they are usually bad coding techniques.