public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/106732] New: lock cannot be generated in a special case
@ 2022-08-24 7:57 benni.probst at gmx dot de
0 siblings, 0 replies; only message in thread
From: benni.probst at gmx dot de @ 2022-08-24 7:57 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106732
Bug ID: 106732
Summary: lock cannot be generated in a special case
Product: gcc
Version: 12.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: benni.probst at gmx dot de
Target Milestone: ---
Created attachment 53500
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=53500&action=edit
CLion bug analysis picture
when using a recursive mutex and a scoped lock or unique lock or lock guard
(does not matter) on the recursive mutex, code cannot be generated even if it
worked in the function above.
//
// Created by benjamin-elias on 09.05.22.
//
#include "config_files.h"
#include "global_custom_functions.h"
#ifndef SCHOOL_PROJECT_DATABASE_CALL_OPS_H
#define SCHOOL_PROJECT_DATABASE_CALL_OPS_H
class database_call_ops {
bool connection_set=false;
std::recursive_mutex database_mutex{};
pqxx::connection *connection;
protected:
std::string addr, p, user, pass, datab;
//TODO: set up connection and custom database call ops
public:
std::string schem, tab;
protected:
bool open=false;
virtual std::string currentSchema() {
const std::lock_guard lock(database_mutex);
return schem;
}
virtual std::string currentTableName() {
const std::lock_guard lock(database_mutex);
return tab;
}
[[nodiscard]] bool isOpen(const std::string &table) const {
const std::scoped_lock lock(database_mutex);
return open and tab==table;
}
std::string currentDatabase() {
return datab;
}
bool checkSchemaExists(const std::string &schema) {
try{
std::string sql = "SELECT EXISTS(SELECT schema_name FROM
information_schema.schemata WHERE schema_name = '"+schema+"');";
custom_function::replace_string_occurencies(sql," "," ");
pqxx::nontransaction n(connection);
pqxx::result r(n.exec(sql));
n.commit();
for (pqxx::result::const_iterator c = r.begin(); c != r.end();) {
auto it = c;
if(++c == r.end())[[likely]]{ return it[0].as<bool>();}
else break;
}
}
catch (std::exception &e){
std::cerr << "checkSchemaExists on " << schema << " failed for this
reason: " << e.what();
}
return false;
}
//returns if schema exists now
bool createSchema(const std::string &schema) {
if (checkSchemaExists(schema))[[likely]]return true;
try{
std::string sql = "CREATE SCHEMA IF NOT EXISTS " + schema + "
AUTHORIZATION " + user + " ; GRANT ALL ON SCHEMA " + schema + " TO " + datab +
" ; GRANT ALL ON SCHEMA " + schema + " TO public;";
custom_function::replace_string_occurencies(sql," "," ");
pqxx::work n(connection);
n.exec(sql);
n.commit();
}
catch (std::exception &e){
std::cerr << "createSchema on " << schema << " failed for this
reason: " << e.what();
exit(EXIT_FAILURE);
}
return checkSchemaExists(schema);
}
bool deleteSchema(const std::string &schema) {
if (!checkSchemaExists(schema))[[unlikely]]{return false;}
try{
std::string sql = "DROP SCHEMA IF EXISTS "+schema+" CASCADE;";
custom_function::replace_string_occurencies(sql," "," ");
pqxx::work n(connection);
n.exec(sql);
n.commit();
}
catch (std::exception &e){
std::cerr << "deleteSchema on " << schema << " failed for this
reason: " << e.what();
}
return !checkSchemaExists(schema);
}
bool checkTableExists(const std::string &schema, const std::string &table)
{
if (!checkSchemaExists(schema))[[unlikely]]{return false;}
try{
std::string sql = "SELECT EXISTS (SELECT FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n"
" ON n.oid = c.relnamespace WHERE n.nspname =
'"+schema+"' AND c.relname = '"+table+
"' AND c.relkind = 'r' );";
custom_function::replace_string_occurencies(sql," "," ");
pqxx::nontransaction n(connection);
pqxx::result r(n.exec(sql));
n.commit();
for (pqxx::result::const_iterator c = r.begin(); c != r.end();) {
auto it = c;
if(++c == r.end())[[likely]]{return it[0].as<bool>();}
else break;
}
}
catch (std::exception &e){
std::cerr << "checkTableExists on (Schema: " << schema << ", Table:
" << table << ") failed for this reason: " << e.what();
}
return false;
}
std::vector<boost::tuple<std::string, std::string>>
table_info(const std::string &schema, const std::string &table) {
std::vector<boost::tuple<std::string,std::string>> out;
try{
//table_name, column_name, data_type
if(!checkTableExists(schema,table))[[unlikely]]{return out;}
std::string sql = "SELECT column_name, data_type FROM
information_schema.columns WHERE table_schema like '"+schema+"%' AND table_name
like '"+table+"%' ;";
custom_function::replace_string_occurencies(sql," "," ");
pqxx::nontransaction n(connection);
pqxx::result r(n.exec(sql));
n.commit();
for (pqxx::result::const_iterator c = r.begin(); c != r.end();) {
out.emplace_back(c[0].as<std::string>(),c[1].as<std::string>());
if(++c == r.end())[[unlikely]]{return out;}
}
}
catch (std::exception &e){
std::cerr << "table_info on (Schema: " << schema << ", Table: " <<
table << ") failed for this reason: " << e.what();
return out;
}
return out;
}
bool deleteTable(const std::string &schema, const std::string &table) {
if (!checkTableExists(schema,table))[[unlikely]]{return false;}
try{
std::string sql = "DROP TABLE IF EXISTS "+schema+"."+table+";";
custom_function::replace_string_occurencies(sql," "," ");
pqxx::work n(connection);
n.exec(sql);
n.commit();
}
catch (std::exception &e){
std::cerr << "deleteTable on (Schema: " << schema << ", Table: " <<
table << ") failed for this reason: " << e.what();
}
return !checkTableExists(schema,table);
}
private:
/*
* this is a variadic function to transform requested types into string
literals that tell the SQL database
* to generate tables with certain data types
*/
template<typename T1, typename T2, typename T3, typename... Args>
std::string createTableRecursiveVariadicDefinition(T1 &&arg1, T2 &&arg2, T3
&&arg3, Args &&... args) {
std::string out;
if constexpr(String<T2>){
if (boost::ifind_first(std::forward<T2>(arg2),
std::string("character varying")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("varchar")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("character")) or
boost::ifind_first(std::forward<T2>(arg2), std::string("char"))
or
boost::ifind_first(std::forward<T2>(arg2), std::string("text"))
or
boost::ifind_first(std::forward<T2>(arg2),
std::string("bytea")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("smallint")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("integer")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("bigint")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("decimal")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("numeric")) or
boost::ifind_first(std::forward<T2>(arg2), std::string("real"))
or
boost::ifind_first(std::forward<T2>(arg2), std::string("double
precision")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("smallserial")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("serial")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("bigserial")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("money")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("timestamp")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("TIMESTAMPTZ")) or
boost::ifind_first(std::forward<T2>(arg2), std::string("date"))
or
boost::ifind_first(std::forward<T2>(arg2),
std::string("a_var")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("interval")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("boolean")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("point")) or
boost::ifind_first(std::forward<T2>(arg2), std::string("line"))
or
boost::ifind_first(std::forward<T2>(arg2), std::string("lseg"))
or
boost::ifind_first(std::forward<T2>(arg2), std::string("box"))
or
boost::ifind_first(std::forward<T2>(arg2), std::string("path"))
or
boost::ifind_first(std::forward<T2>(arg2),
std::string("polygon")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("circle")) or
boost::ifind_first(std::forward<T2>(arg2), std::string("cidr"))
or
boost::ifind_first(std::forward<T2>(arg2), std::string("inet"))
or
boost::ifind_first(std::forward<T2>(arg2),
std::string("macaddr")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("tsvector")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("tsquery")) or
boost::ifind_first(std::forward<T2>(arg2), std::string("any"))
or
boost::ifind_first(std::forward<T2>(arg2),
std::string("anyelement")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("anyarray")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("anynonarray")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("anyenum")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("anyrange")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("cstring")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("internal")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("language_handler")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("fdw_handler")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("record")) or
boost::ifind_first(std::forward<T2>(arg2),
std::string("trigger")) or
boost::ifind_first(std::forward<T2>(arg2), std::string("void"))
){
out+=(std::string) std::forward<T1>(arg1)+" "+(std::string)
std::forward<T2>(arg2)+" "+(std::string) std::forward<T3>(arg3);
}
else{
if constexpr(sizeof...(args)==0){
out+=(std::string) std::forward<T1>(arg1)+" "+(std::string)
std::forward<T2>(arg2)+" "+(std::string) std::forward<T3>(arg3);
}
else{
out+=(std::string) std::forward<T1>(arg1)+" text
"+(std::string) std::forward<T3>(arg3);
}
}
}
else{
if constexpr(std::is_same_v<typename std::decay<T2>::type,unsigned
char> or
std::is_same_v<typename std::decay<T2>::type,unsigned
short> or
std::is_same_v<typename std::decay<T2>::type,char> or
std::is_same_v<typename std::decay<T2>::type,short>
){
out+=(std::string) std::forward<T1>(arg1)+" smallint
"+(std::string) std::forward<T3>(arg3);
}
if constexpr(std::is_same_v<typename std::decay<T2>::type,unsigned
int> or
std::is_same_v<typename std::decay<T2>::type,int>
){
out+=(std::string) std::forward<T1>(arg1)+" integer
"+(std::string) std::forward<T3>(arg3);
}
if constexpr(std::is_same_v<typename std::decay<T2>::type,unsigned
long int> or
std::is_same_v<typename std::decay<T2>::type,unsigned
long long int> or
std::is_same_v<typename std::decay<T2>::type,long int>
or
std::is_same_v<typename std::decay<T2>::type,long long
int>
){
out+=(std::string) std::forward<T1>(arg1)+" bigint
"+(std::string) std::forward<T3>(arg3);
}
if constexpr(std::is_same_v<typename std::decay<T2>::type,float>){
out+=(std::string) std::forward<T1>(arg1)+" real
"+(std::string) std::forward<T3>(arg3);
}
if constexpr(std::is_same_v<typename std::decay<T2>::type,double>
or
std::is_same_v<typename std::decay<T2>::type,long
double>
){
out+=(std::string) std::forward<T1>(arg1)+" double precision
"+(std::string) std::forward<T3>(arg3);
}
if constexpr(std::is_same_v<typename std::decay<T2>::type,bool>){
out+=(std::string) std::forward<T1>(arg1)+" boolean
"+(std::string) std::forward<T3>(arg3);
}
}
if constexpr(sizeof...(args)==0){
return out;
}
else{
return out+", "+createTableRecursiveVariadicDefinition(args...);
}
}
public:
bool connect(const std::string &database) {
if(connection.is_open())[[likely]]{
std::cout << "Database " << database << " was already open.";
return true;
}
INFO << "Connecting on Database " << database;
for (char i = 0; i < 3; i++) {
try {
std::string out =
"user=" + user + " password=" + pass + " host=" + addr
+ " port=" + p + " dbname=postgres" + " target_settion_attrs=read-write";
connection = pqxx::connection(out);
if (connection.is_open())[[likely]]{
std::cout << "Opened database successfully: " <<
this->datab;
datab = database;
return true;
} else {
CUSTOM_THROW(1,"Can't open database")
}
} catch (const std::exception &e) {
std::cerr << "connect on Database " << database << " failed for
this reason: " << e.what();
std::system("service postgresql restart");
std::cout << "Restart of database done!";
}
}
if(!connection.is_open())[[likely]]{
std::cerr << "Database " << database << " could finally not be
connected to!";
exit(EXIT_FAILURE);
}
return false;
}
void disconnect() {
connection.close();
}
//this function creates a table and will also create the schema if it does
not exist
template<typename... Args>
bool createTable(const std::string &schema, const std::string &table, const
std::string &pre_options,
const std::string &options, Args &&... args) {
if(!checkSchemaExists(schema))[[unlikely]]{
if(!createSchema(schema))[[unlikely]]{
std::cerr << "The following schema could not be created: " <<
schema;
exit(EXIT_FAILURE);
}
}
if(checkTableExists(schema,table))[[likely]]{return false;}
std::string sql = "CREATE "+pre_options+" TABLE "+options+"
"+schema+"."+table+" ( "+createTableRecursiveVariadicDefinition(args...)+" )
;";
while(boost::algorithm::contains(sql," ")){
custom_function::replace_string_occurencies(sql," "," ");
}
try{
pqxx::work n(connection);
n.exec(sql);
n.commit();
}
catch (std::exception &e){
std::cerr << "createTable on (SQL command: " << sql << ") failed
for this reason: " << e.what();
exit(EXIT_FAILURE);
}
return checkTableExists(schema,table);
}
/*
* automatically open table and create scheme or table if it does not
exists
*/
template<typename... Args>
bool openTable(const std::string &database, const std::string &schema,
const std::string &table,Args &&...args) {
if(!connect(database))[[unlikely]]{
std::cerr << "Could not connect to database and clName: " <<
database << " at " << schema << "." << table << " !!!";
std::exit(EXIT_FAILURE);
}
schem=schema;
tab=table;
if (checkTableExists(schema,table))[[likely]]{
open = true;
return open;
}
else{
open=this->createTable(schema,table,args...);
if (!open){
std::cerr << "Cannot create tabel for open request (database:
"<< database << ", schema: "
<< schema << ", table: "<< table << ")";
return open;
}
return open;
}
}
//check if the block can be reader
bool check_block_exists(const std::string& identifier) {
std::string sql = "SELECT identifier FROM " + schem + "." + tab + "
WHERE identifier = decodeInit('"+ identifier + "', 'hex');";
custom_function::replace_string_occurencies(sql," "," ");
pqxx::nontransaction nf(connection);
pqxx::result rf(nf.exec(sql));
nf.commit();
if (rf.empty()) {
return false;
}
return rf[0][0].as<std::string>()==identifier;
}
//get the value of the sha id, so basically retrieve/return block
std::string read_block(const std::string& identifier) {
if(!check_block_exists(identifier))[[unlikely]]{
std::cerr << "The block "+identifier+"was not found on the
database." << std::endl;
std::exit(EXIT_FAILURE);
}
std::string sql = "SELECT identifier,block FROM " + schem + "." + tab +
" WHERE identifier = decodeInit('" + identifier + "', 'hex');";
custom_function::replace_string_occurencies(sql," "," ");
pqxx::nontransaction nf(connection);
pqxx::result rf(nf.exec(sql));
nf.commit();
if(rf.size()>1){
std::cerr << "The block hash "+identifier+"was found multiple times
on the database." << std::endl;
}
return rf[0][1].as<std::string>();
}
//write block by setting a string to the sha_id
bool write_block(const std::string& identifier, const std::string& block) {
if(check_block_exists(identifier))[[unlikely]]{
std::cerr << "The block "+identifier+"was found on the database and
will be updated." << std::endl;
}
std::string sql =
"INSERT INTO " + this->schem + "." + this->tab + "
(identifier,block) VALUES (decodeInit('" + identifier +"', 'hex'),
decodeInit('" + block +"', 'hex')) ON CONFLICT (identifier) DO UPDATE SET block
= excluded.block ;";
custom_function::replace_string_occurencies(sql," "," ");
pqxx::work n2(connection);
n2.exec(sql);
n2.commit();
return true;
}
//auto create block table
explicit database_call_ops(const std::string &db_config_file) {//:
postgresSQL(db_config_file) {
try{
std::filesystem::path config(db_config_file);
config_files configuration = config_files(config);
unsigned char count=0;
for(auto &r:configuration.read()){
switch(count){
case 0:addr=r;break;
case 1:p=r;break;
case 2:user=r;break;
case 3:pass=r;break;
case 4:datab=r;break;
case 5:schem=r;break;
default:tab=r;break;
}
count++;
}
std::cout << "Successfully reader Database configuration file at
postgreSQL \'" << config.c_str() << "\' module." ;
}
catch (std::exception &e){
try{
std::fstream file;
file.exceptions(std::ofstream::failbit |
std::ofstream::badbit);
file.open(db_config_file, std::ios_base::binary);
(void) file.write(std::string().c_str(), 0);
file.close();
std::cerr<<"Could not configure Database, because there was a
file error (check please) at postgreSQL \'config_database\' (address: "+addr+",
port: "+p+", user: "+user+", password: "+pass+") error: " << e.what();
std::cout<<"Created a new database config file at the spot you
chose. Hopefully this was not by accident so you should not forget to delete
the file at the wrong spot.";
}
catch(std::exception& e){
std::cerr<<"Could not configure Database, because there was a
file error (check please) at postgreSQL \'config_database\' (address: "+addr+",
port: "+p+", user: "+user+", password: "+pass+") error: " << e.what();
std::exit(EXIT_FAILURE);
}
}
if (!this->openTable(datab, schem, tab, "", "IF NOT EXISTS",
"id", (unsigned long long int) 0, "GENERATED
ALWAYS AS IDENTITY",
"identifier", "bytea", "UNIQUE NOT NULL",
"block", "bytea", "NOT NULL",
"", "", "PRIMARY KEY(id)"
)) {
std::cerr << "Database table could not be created or opened!";
std::exit(EXIT_FAILURE);
}
}
};
#endif //SCHOOL_PROJECT_DATABASE_CALL_OPS_H
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-08-24 7:57 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-24 7:57 [Bug c++/106732] New: lock cannot be generated in a special case benni.probst at gmx dot de
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).