Closed jigar88 closed 3 years ago
Use _Server::runserver and Arc<RwLock
let server = Arc::new(RwLock::new(new_server(0)));
let server2 = server.clone();
let (tx, rx) = channel();
let _t = thread::spawn(move || {
// This should run & block until it is told to abort
Server::run_server(server);
tx.send(()).unwrap();
});
{
let server = server2.write().unwrap();
...
}
@schroeder- I am not quite getting it, but I will keep tying to troubleshoot.
If you need to store a variable multiple times with different lifetimes you normally store the variable as refcounted variable. If you are single threaded you use Rc
When you call server.run() it basically blocks the current thread so nothing else will happen until it exits. If you want to do other stuff then spawn a thread and run the server from that and carry on in the other thread.
It's hard to say what you want to do from the rest of the code, but you there are two ways of setting values on variables in the server - either you can just set the value and let the server manage it or you can register a getter which is called to retrieve the value that you manage.
The simple_server demonstrates both of these with variables hooked up to be set from a timer or called when the value is needed. It really depends what you're doing which is the best approach but I provide both as ways to do it.
Okay I am trying to use Arc with Mutex to reuse server variable multiple time.
pub fn run_opc_server() {
let mut server = Server::new(ServerConfig::load(&PathBuf::from("/tmp/server.conf")).unwrap());
let server2 = Arc::new(Mutex::new(server));
let server2 = Arc::clone(&server2);
let ns = {
let address_space = server2.lock().unwrap().address_space();
let mut address_space = address_space.write().unwrap();
address_space.register_namespace("EMS").unwrap()
};
global_opc_nodes::create_global_variables(&mut server2.lock().unwrap(), ns);
server2.lock().unwrap().run();
This gives an error
error[E0507]: cannot move out of dereference of `std::sync::MutexGuard<'_, opcua_server::server::Server>`
--> src/opc_server.rs:22:5
|
22 | server2.lock().unwrap().run();
| ^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `opcua_server::server::Server`, which does not implement the `Copy` trait
and same result with RwLock
let server = Server::new(ServerConfig::load(&PathBuf::from("/tmp/server.conf")).unwrap());
let server2 = Arc::new(RwLock::new(server));
let server2 = Arc::clone(&server2);
let ns = {
let address_space = server2.write().unwrap().address_space();
let mut address_space = address_space.write().unwrap();
address_space.register_namespace("EMS").unwrap()
};
global_opc_nodes::create_global_variables(&mut server2.write().unwrap(), ns);
server2.write().unwrap().run();
You have to call Server::run_server, if you want to use an Arc<RwLock
let server2 = Arc::new(RwLock::new(.........));
Server::run_server(server2);
Ok , I have reached halfway. Now opc server starts but then I want to use same server variable for tcp server loop. But now it gives error that variable moved to closure so you can't borrow.
pub fn run_opc_server() {
let server = Server::new(ServerConfig::load(&PathBuf::from("/tmp/server.conf")).unwrap());
let server2 = Arc::new(RwLock::new(server));
let server2 = Arc::clone(&server2);
let ns = {
let address_space = server2.write().unwrap().address_space();
let mut address_space = address_space.write().unwrap();
address_space.register_namespace("EMS").unwrap()
};
global_opc_nodes::create_global_variables(&mut server2.write().unwrap(), ns);
thread::spawn(move || Server::run_server(server2));
println!("OPC Server stared and running...");
process_incoming_tcp_messages::run(&mut server2.write().unwrap(), ns);
}
gives error:
error[E0382]: borrow of moved value: server2
--> src/opc_server.rs:21:46 |
12 | let server2 = Arc::clone(&server2); | ------- move occurs because server2 has type std::sync::Arc<std::sync::RwLock<opcua_server::server::Server>> , which does not implement the Copy trait
...
19 |
thread::spawn(move | Server::run_server(server2)); | ------- ------- variable moved due to use in closure | |
---|---|---|---|---|---|---|---|
value moved into closure here | |||||||
20 | println!("OPC Server stared and running..."); | ||||||
21 | process_incoming_tcp_messages::run(&mut server2.write().unwrap(), ns); | ||||||
^^^^^^^ value borrowed here after move |
Maybe you should read about how to use shared state in rust: rwlock rust book
For your problem you can clone an Arc before spawn a thread.
pub fn run_opc_server() {
let server = Server::new(ServerConfig::load(&PathBuf::from("/tmp/server.conf")).unwrap());
let server2 = Arc::new(RwLock::new(server));
let ns = {
let address_space = server2.write().unwrap().address_space();
let mut address_space = address_space.write().unwrap();
address_space.register_namespace("EMS").unwrap()
};
global_opc_nodes::create_global_variables(&mut server2.write().unwrap(), ns);
let server_th = server2.clone();
thread::spawn(move || Server::run_server(server_th ));
println!("OPC Server stared and running...");
process_incoming_tcp_messages::run(&mut server2.write().unwrap(), ns);
}
so I have both servers working now, its just sometimes not connecting in time. opc server takes little longer to connect but I am able to process messages on opc server from tcp server. I ended up doing
pub fn run_opc_server() {
let opc_server = Server::new(ServerConfig::load(&PathBuf::from("/tmp/server.conf")).unwrap());
let opc_server_arc_object = Arc::new(RwLock::new(opc_server));
let ns = {
let address_space = opc_server_arc_object.write().unwrap().address_space();
let mut address_space = address_space.write().unwrap();
address_space.register_namespace("EMS").unwrap()
};
global_opc_nodes::create_global_variables(&mut opc_server_arc_object.write().unwrap(), ns);
let threaded_server_object = opc_server_arc_object.clone();
thread::spawn(move || Server::run_server(threaded_server_object));
// let sts = NodeId::new(0, 2256);
// let v = DataValue::new_now(sts.clone());
loop {
thread::sleep(time::Duration::from_secs(30));
let threaded_server_for_nodes = opc_server_arc_object.clone();
thread::spawn(move || process_incoming_tcp_messages::run(&mut threaded_server_for_nodes.write().unwrap(), ns));
}
}
Closing because remaining issues are probably race conditions in the implementation using the crate
Hello I am trying to create lot of nodes from the messages receiving from tcp server. I tried to follow demo server code but I have an issue for borrowing the server variable. I am newbie to rust as well. Can someone help to resolve the issue. I have continuous loop in the one of the rust file so opc server never gets start. This is more related to rust but due to opc code involvement I just want to get help from here if someone can.
Module: simulator
main.rs
client.rs
Module: src
main.rs
opc_server.rs
in this code is there a better way I can use server variable, if I try to create a thread it gives error of can't borrow moved variable.
global_nodes.rs
process_tcp_messages.rs
I have a infinite loop here to process tcp server messages received from client. I try to put this code in thread but did not work , may be I am not doing proper threading. Based on the received message, I will create nodes and update its values continuously. Currently that function is comment out.