Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
dCache
cta
Commits
c1ab4b55
Commit
c1ab4b55
authored
May 26, 2016
by
Steven Murray
Browse files
Extended the syntax of the CTA database configuration file to support both in-memory and oracle
parent
5aca316b
Changes
10
Hide whitespace changes
Inline
Side-by-side
catalogue/CMakeLists.txt
View file @
c1ab4b55
...
...
@@ -66,6 +66,7 @@ add_custom_command(OUTPUT RdbmsCatalogueSchema.cpp
DEPENDS catalogue_schema.cpp
)
set
(
CATALOGUE_UNIT_TESTS_LIB_SRC_FILES
DbLoginTest.cpp
RdbmsCatalogueTest.cpp
SqliteStmtTest.cpp
)
...
...
@@ -90,3 +91,7 @@ target_link_libraries (ctacatalogueoraunittests
ctacatalogue
)
install
(
TARGETS ctacatalogueoraunittests DESTINATION usr/
${
CMAKE_INSTALL_LIBDIR
}
)
install
(
FILES cta_catalogue_db.conf.example
DESTINATION
${
CMAKE_INSTALL_SYSCONFDIR
}
/cta
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
catalogue/DbLogin.cpp
View file @
c1ab4b55
...
...
@@ -20,44 +20,30 @@
#include
"common/exception/Exception.hpp"
#include
"common/utils/utils.hpp"
#include
<errno.h>
#include
<fstream>
#include
<iostream>
#include
<list>
#include
<memory>
#include
<stdint.h>
#include
<sstream>
#include
<stdio.h>
#include
<stdexcept>
#include
<string.h>
namespace
{
namespace
cta
{
namespace
catalogue
{
using
namespace
cta
;
namespace
{
/**
* Reads the entire contents of the specified
files
and returns a list of the
* Reads the entire contents of the specified
stream
and returns a list of the
* non-empty lines.
*
* A line is considered not empty if it contains characters that are not white
* space and are not part of a comment.
*
* @param is The input stream.
* @return A list of the non-empty lines.
*/
std
::
list
<
std
::
string
>
readNonEmptyLines
(
const
std
::
string
&
filename
)
{
std
::
ifstream
file
(
filename
);
if
(
!
file
)
{
exception
::
Exception
ex
;
ex
.
getMessage
()
<<
"Failed to open "
<<
filename
;
throw
ex
;
}
std
::
list
<
std
::
string
>
readNonEmptyLines
(
std
::
istream
&
inputStream
)
{
std
::
list
<
std
::
string
>
lines
;
std
::
string
line
;
while
(
std
::
getline
(
file
,
line
))
{
while
(
std
::
getline
(
inputStream
,
line
))
{
// Remove the newline character if there is one
{
const
std
::
string
::
size_type
newlinePos
=
line
.
find
(
"
\n
"
);
...
...
@@ -88,51 +74,80 @@ std::list<std::string> readNonEmptyLines(
}
// anonymous namespace
namespace
cta
{
namespace
catalogue
{
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
DbLogin
::
DbLogin
(
const
DbType
dbType
,
const
std
::
string
&
username
,
const
std
::
string
&
password
,
const
std
::
string
&
database
)
:
dbType
(
dbType
),
username
(
username
),
password
(
password
),
database
(
database
)
{
}
//------------------------------------------------------------------------------
//
readFrom
File
//
parse
File
//------------------------------------------------------------------------------
DbLogin
DbLogin
::
readFromFile
(
const
std
::
string
&
filename
)
{
const
std
::
string
fileFormat
=
"username/password@database"
;
const
std
::
list
<
std
::
string
>
lines
=
readNonEmptyLines
(
filename
);
DbLogin
DbLogin
::
parseFile
(
const
std
::
string
&
filename
)
{
try
{
std
::
ifstream
file
(
filename
);
if
(
!
file
)
{
throw
exception
::
Exception
(
"Failed to open file"
);
}
return
parseStream
(
file
);
}
catch
(
exception
::
Exception
&
ex
)
{
throw
exception
::
Exception
(
std
::
string
(
"Failed to parse database login file "
+
filename
+
": "
+
ex
.
getMessage
().
str
()));
}
}
//------------------------------------------------------------------------------
// parseStream
//------------------------------------------------------------------------------
DbLogin
DbLogin
::
parseStream
(
std
::
istream
&
inputStream
)
{
const
std
::
string
fileFormat
=
"either in_memory or oracle:username/password@database"
;
const
std
::
list
<
std
::
string
>
lines
=
readNonEmptyLines
(
inputStream
);
if
(
1
!=
lines
.
size
())
{
std
::
ostringstream
msg
;
msg
<<
filename
<<
" should contain one and only one connection string"
;
throw
exception
::
Exception
(
msg
.
str
());
throw
exception
::
Exception
(
"There should only be one and only one line containing a connection string"
);
}
const
std
::
string
connectionString
=
lines
.
front
();
if
(
connectionString
==
"in_memory"
)
{
const
std
::
string
username
=
""
;
const
std
::
string
password
=
""
;
const
std
::
string
database
=
""
;
return
DbLogin
(
DBTYPE_IN_MEMORY
,
username
,
password
,
database
);
}
std
::
vector
<
std
::
string
>
typeAndDetails
;
// Where details are username, password and database
utils
::
splitString
(
connectionString
,
':'
,
typeAndDetails
);
if
(
2
!=
typeAndDetails
.
size
())
{
throw
exception
::
Exception
(
std
::
string
(
"Invalid connection string: Correct format is "
)
+
fileFormat
);
}
if
(
typeAndDetails
[
0
]
!=
"oracle"
)
{
throw
exception
::
Exception
(
std
::
string
(
"Invalid connection string: Correct format is "
)
+
fileFormat
);
}
std
::
vector
<
std
::
string
>
userPassAndDb
;
utils
::
splitString
(
connectionString
,
'@'
,
userPassAndDb
);
utils
::
splitString
(
typeAndDetails
[
1
]
,
'@'
,
userPassAndDb
);
if
(
2
!=
userPassAndDb
.
size
())
{
throw
exception
::
Exception
(
std
::
string
(
"Invalid connection string"
": Correct format is "
)
+
fileFormat
);
throw
exception
::
Exception
(
std
::
string
(
"Invalid connection string: Correct format is "
)
+
fileFormat
);
}
std
::
vector
<
std
::
string
>
userAndPass
;
utils
::
splitString
(
userPassAndDb
[
0
],
'/'
,
userAndPass
);
if
(
2
!=
userAndPass
.
size
())
{
throw
exception
::
Exception
(
std
::
string
(
"Invalid connection string"
": Correct format is "
)
+
fileFormat
);
throw
exception
::
Exception
(
std
::
string
(
"Invalid connection string: Correct format is "
)
+
fileFormat
);
}
return
DbLogin
(
userAndPass
[
0
],
userAndPass
[
1
],
userPassAndDb
[
1
]);
return
DbLogin
(
DBTYPE_ORACLE
,
userAndPass
[
0
],
userAndPass
[
1
],
userPassAndDb
[
1
]);
}
}
// namesapce catalogue
...
...
catalogue/DbLogin.hpp
View file @
c1ab4b55
...
...
@@ -18,6 +18,7 @@
#pragma once
#include
<istream>
#include
<string>
namespace
cta
{
...
...
@@ -28,18 +29,34 @@ namespace catalogue {
*/
struct
DbLogin
{
/**
* Enumeration of the supported database types.
*/
enum
DbType
{
DBTYPE_IN_MEMORY
,
DBTYPE_ORACLE
,
DBTYPE_NONE
};
/**
* Constructor.
*
* @param dbType The type of the database.
* @param username The username.
* @param password The password.
* @param database The database name.
*/
DbLogin
(
const
DbType
dbType
,
const
std
::
string
&
username
,
const
std
::
string
&
password
,
const
std
::
string
&
database
);
/**
* The type of the database.
*/
DbType
dbType
;
/**
* The user name.
*/
...
...
@@ -56,15 +73,44 @@ struct DbLogin {
std
::
string
database
;
/**
* Reads the database login information from the specified file. The format
* of the file is:
* Reads and parses the database login information from the specified file.
*
* The input stream must contain one and only one connection string.
*
* The format of the connection string is:
*
* in_memory or oracle:username/password@database
*
* The file can contain multiple empty lines.
*
* The file can contain multiple comment lines where a comment
* line starts with optional whitespace and a hash character '#'.
*
* @param filename The name of the file containing the database login
* information.
* @return The database login information.
*/
static
DbLogin
parseFile
(
const
std
::
string
&
filename
);
/**
* Reads and parses the database login information from the specified input
* stream.
*
* The input stream must contain one and only one connection string.
*
* The format of the connection string is:
*
* in_memory or oracle:username/password@database
*
* The input stream can contain multiple empty lines.
*
* username/password@database
* The input stream can contain multiple comment lines where a comment
* line starts with optional whitespace and a hash character '#'.
*
* @param
The name of the file containing the database login information
.
* @param
inputStream The input stream to be read from
.
* @return The database login information.
*/
static
DbLogin
readFromFile
(
const
std
::
str
ing
&
filen
am
e
);
static
DbLogin
parseStream
(
std
::
i
str
eam
&
inputStre
am
);
};
// class DbLogin
...
...
catalogue/DbLoginTest.cpp
0 → 100644
View file @
c1ab4b55
/*
* The CERN Tape Archive (CTA) project
* Copyright (C) 2015 CERN
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include
"catalogue/DbLogin.hpp"
#include
"common/exception/Exception.hpp"
#include
<gtest/gtest.h>
#include
<sstream>
namespace
unitTests
{
class
cta_catalogue_DbLoginTest
:
public
::
testing
::
Test
{
protected:
virtual
void
SetUp
()
{
}
virtual
void
TearDown
()
{
}
};
TEST_F
(
cta_catalogue_DbLoginTest
,
constructor
)
{
using
namespace
cta
::
catalogue
;
const
DbLogin
inMemoryLogin
(
DbLogin
::
DBTYPE_IN_MEMORY
,
""
,
""
,
""
);
ASSERT_EQ
(
DbLogin
::
DBTYPE_IN_MEMORY
,
inMemoryLogin
.
dbType
);
ASSERT_TRUE
(
inMemoryLogin
.
username
.
empty
());
ASSERT_TRUE
(
inMemoryLogin
.
password
.
empty
());
ASSERT_TRUE
(
inMemoryLogin
.
database
.
empty
());
const
DbLogin
oracleLogin
(
DbLogin
::
DBTYPE_ORACLE
,
"username"
,
"password"
,
"database"
);
ASSERT_EQ
(
DbLogin
::
DBTYPE_ORACLE
,
oracleLogin
.
dbType
);
ASSERT_EQ
(
std
::
string
(
"username"
),
oracleLogin
.
username
);
ASSERT_EQ
(
std
::
string
(
"password"
),
oracleLogin
.
password
);
ASSERT_EQ
(
std
::
string
(
"database"
),
oracleLogin
.
database
);
}
TEST_F
(
cta_catalogue_DbLoginTest
,
parseStream_in_memory
)
{
using
namespace
cta
::
catalogue
;
std
::
stringstream
inputStream
;
inputStream
<<
"# A comment"
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
inputStream
<<
"# Another comment"
<<
std
::
endl
;
inputStream
<<
"in_memory"
;
inputStream
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
const
DbLogin
dbLogin
=
DbLogin
::
parseStream
(
inputStream
);
ASSERT_EQ
(
DbLogin
::
DBTYPE_IN_MEMORY
,
dbLogin
.
dbType
);
ASSERT_TRUE
(
dbLogin
.
username
.
empty
());
ASSERT_TRUE
(
dbLogin
.
password
.
empty
());
ASSERT_TRUE
(
dbLogin
.
database
.
empty
());
}
TEST_F
(
cta_catalogue_DbLoginTest
,
parseStream_oracle
)
{
using
namespace
cta
::
catalogue
;
std
::
stringstream
inputStream
;
inputStream
<<
"# A comment"
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
inputStream
<<
"# Another comment"
<<
std
::
endl
;
inputStream
<<
"oracle:username/password@database"
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
const
DbLogin
dbLogin
=
DbLogin
::
parseStream
(
inputStream
);
ASSERT_EQ
(
DbLogin
::
DBTYPE_ORACLE
,
dbLogin
.
dbType
);
ASSERT_EQ
(
std
::
string
(
"username"
),
dbLogin
.
username
);
ASSERT_EQ
(
std
::
string
(
"password"
),
dbLogin
.
password
);
ASSERT_EQ
(
std
::
string
(
"database"
),
dbLogin
.
database
);
}
TEST_F
(
cta_catalogue_DbLoginTest
,
parseStream_invalid
)
{
using
namespace
cta
;
using
namespace
cta
::
catalogue
;
std
::
stringstream
inputStream
;
inputStream
<<
"# A comment"
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
inputStream
<<
"# Another comment"
<<
std
::
endl
;
inputStream
<<
"invalid_connection_string"
;
inputStream
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
inputStream
<<
std
::
endl
;
ASSERT_THROW
(
DbLogin
::
parseStream
(
inputStream
),
exception
::
Exception
);
}
}
// namespace unitTests
catalogue/OcciConnTest.cpp
View file @
c1ab4b55
...
...
@@ -24,6 +24,7 @@
#include
<gtest/gtest.h>
#include
<memory>
#include
<sstream>
namespace
unitTests
{
...
...
@@ -52,7 +53,7 @@ TEST_F(cta_catalogue_OcciConnTest, constructor_real_connection) {
using
namespace
cta
;
using
namespace
cta
::
catalogue
;
const
DbLogin
dbLogin
=
DbLogin
::
readFrom
File
(
g_cmdLineArgs
.
oraDbConnFile
);
const
DbLogin
dbLogin
=
DbLogin
::
parse
File
(
g_cmdLineArgs
.
oraDbConnFile
);
OcciEnv
env
;
std
::
unique_ptr
<
DbConn
>
conn
(
env
.
createConn
(
dbLogin
.
username
.
c_str
(),
...
...
@@ -64,7 +65,7 @@ TEST_F(cta_catalogue_OcciConnTest, createStmt_null_sql) {
using
namespace
cta
;
using
namespace
cta
::
catalogue
;
const
DbLogin
dbLogin
=
DbLogin
::
readFrom
File
(
g_cmdLineArgs
.
oraDbConnFile
);
const
DbLogin
dbLogin
=
DbLogin
::
parse
File
(
g_cmdLineArgs
.
oraDbConnFile
);
OcciEnv
env
;
std
::
unique_ptr
<
DbConn
>
conn
(
env
.
createConn
(
dbLogin
.
username
.
c_str
(),
...
...
@@ -78,7 +79,7 @@ TEST_F(cta_catalogue_OcciConnTest, createStmt) {
using
namespace
cta
;
using
namespace
cta
::
catalogue
;
const
DbLogin
dbLogin
=
DbLogin
::
readFrom
File
(
g_cmdLineArgs
.
oraDbConnFile
);
const
DbLogin
dbLogin
=
DbLogin
::
parse
File
(
g_cmdLineArgs
.
oraDbConnFile
);
OcciEnv
env
;
std
::
unique_ptr
<
DbConn
>
conn
(
env
.
createConn
(
dbLogin
.
username
.
c_str
(),
...
...
catalogue/OcciRsetTest.cpp
View file @
c1ab4b55
...
...
@@ -43,7 +43,7 @@ TEST_F(cta_catalogue_OcciRsetTest, executeQuery) {
using
namespace
cta
;
using
namespace
cta
::
catalogue
;
const
DbLogin
dbLogin
=
DbLogin
::
readFrom
File
(
g_cmdLineArgs
.
oraDbConnFile
);
const
DbLogin
dbLogin
=
DbLogin
::
parse
File
(
g_cmdLineArgs
.
oraDbConnFile
);
OcciEnv
env
;
std
::
unique_ptr
<
DbConn
>
conn
(
env
.
createConn
(
dbLogin
.
username
.
c_str
(),
...
...
@@ -62,7 +62,7 @@ TEST_F(cta_catalogue_OcciRsetTest, executeQueryRelyOnRsetDestructorForCacheDelet
using
namespace
cta
;
using
namespace
cta
::
catalogue
;
const
DbLogin
dbLogin
=
DbLogin
::
readFrom
File
(
g_cmdLineArgs
.
oraDbConnFile
);
const
DbLogin
dbLogin
=
DbLogin
::
parse
File
(
g_cmdLineArgs
.
oraDbConnFile
);
OcciEnv
env
;
std
::
unique_ptr
<
DbConn
>
conn
(
env
.
createConn
(
dbLogin
.
username
.
c_str
(),
...
...
@@ -80,7 +80,7 @@ TEST_F(cta_catalogue_OcciRsetTest, executeQuery_uint32_t) {
using
namespace
cta
;
using
namespace
cta
::
catalogue
;
const
DbLogin
dbLogin
=
DbLogin
::
readFrom
File
(
g_cmdLineArgs
.
oraDbConnFile
);
const
DbLogin
dbLogin
=
DbLogin
::
parse
File
(
g_cmdLineArgs
.
oraDbConnFile
);
OcciEnv
env
;
std
::
unique_ptr
<
DbConn
>
conn
(
env
.
createConn
(
dbLogin
.
username
.
c_str
(),
...
...
@@ -101,7 +101,7 @@ TEST_F(cta_catalogue_OcciRsetTest, bind_c_string) {
using
namespace
cta
;
using
namespace
cta
::
catalogue
;
const
DbLogin
dbLogin
=
DbLogin
::
readFrom
File
(
g_cmdLineArgs
.
oraDbConnFile
);
const
DbLogin
dbLogin
=
DbLogin
::
parse
File
(
g_cmdLineArgs
.
oraDbConnFile
);
OcciEnv
env
;
std
::
unique_ptr
<
DbConn
>
conn
(
env
.
createConn
(
dbLogin
.
username
.
c_str
(),
...
...
@@ -121,7 +121,7 @@ TEST_F(cta_catalogue_OcciRsetTest, bind_uint32_t) {
using
namespace
cta
;
using
namespace
cta
::
catalogue
;
const
DbLogin
dbLogin
=
DbLogin
::
readFrom
File
(
g_cmdLineArgs
.
oraDbConnFile
);
const
DbLogin
dbLogin
=
DbLogin
::
parse
File
(
g_cmdLineArgs
.
oraDbConnFile
);
OcciEnv
env
;
std
::
unique_ptr
<
DbConn
>
conn
(
env
.
createConn
(
dbLogin
.
username
.
c_str
(),
...
...
catalogue/OcciStmtTest.cpp
View file @
c1ab4b55
...
...
@@ -42,7 +42,7 @@ TEST_F(cta_catalogue_DbStmtTest, executeQuery) {
using
namespace
cta
;
using
namespace
cta
::
catalogue
;
const
DbLogin
dbLogin
=
DbLogin
::
readFrom
File
(
g_cmdLineArgs
.
oraDbConnFile
);
const
DbLogin
dbLogin
=
DbLogin
::
parse
File
(
g_cmdLineArgs
.
oraDbConnFile
);
OcciEnv
env
;
std
::
unique_ptr
<
DbConn
>
conn
(
env
.
createConn
(
dbLogin
.
username
.
c_str
(),
...
...
catalogue/SqliteConnTest.cpp
deleted
100644 → 0
View file @
5aca316b
#include
"catalogue/SqliteConn.hpp"
#include
"common/exception/Exception.hpp"
#include
<gtest/gtest.h>
#include
<memory>
namespace
unitTests
{
class
cta_catalogue_SqliteConnTest
:
public
::
testing
::
Test
{
protected:
virtual
void
SetUp
()
{
}
virtual
void
TearDown
()
{
}
};
TEST_F
(
cta_catalogue_SqliteConnTest
,
constructor
)
{
using
namespace
cta
::
catalogue
;
std
::
unique_ptr
<
SqliteConn
>
db
;
ASSERT_NO_THROW
(
db
.
reset
(
new
SqliteConn
(
":memory:"
)));
}
TEST_F
(
cta_catalogue_SqliteConnTest
,
enableForeignKeys
)
{
using
namespace
cta
::
catalogue
;
std
::
unique_ptr
<
SqliteConn
>
db
;
ASSERT_NO_THROW
(
db
.
reset
(
new
SqliteConn
(
":memory:"
)));
ASSERT_NO_THROW
(
db
->
enableForeignKeys
());
}
TEST_F
(
cta_catalogue_SqliteConnTest
,
createTable
)
{
using
namespace
cta
::
catalogue
;
std
::
unique_ptr
<
SqliteConn
>
db
;
ASSERT_NO_THROW
(
db
.
reset
(
new
SqliteConn
(
":memory:"
)));
ASSERT_NO_THROW
(
db
->
execNonQuery
(
"CREATE TABLE TEST(COL1 INTEGER);"
));
}
TEST_F
(
cta_catalogue_SqliteConnTest
,
createSameTableTwice
)
{
using
namespace
cta
::
catalogue
;
std
::
unique_ptr
<
SqliteConn
>
db
;
ASSERT_NO_THROW
(
db
.
reset
(
new
SqliteConn
(
":memory:"
)));
ASSERT_NO_THROW
(
db
->
execNonQuery
(
"CREATE TABLE TEST(COL1 INTEGER);"
));
ASSERT_THROW
(
db
->
execNonQuery
(
"CREATE TABLE TEST(COL1 INTEGER);"
),
cta
::
exception
::
Exception
);
}
}
// namespace unitTests
catalogue/cta_catalogue_db.conf.example
0 → 100644
View file @
c1ab4b55
# The CERN Tape Archive (CTA) project
# Copyright (C) 2015 CERN
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This file should contain one and only one connection string. Blank lines and
# comments are ignored. The format of the connection string is either:
#
# in_memory
#
# or:
#
# oracle:username/password@database
cta.spec.in
View file @
c1ab4b55
...
...
@@ -133,6 +133,7 @@ The shared libraries
%attr(0755,root,root) %{_libdir}/libctamessagesutils.so
%attr(0755,root,root) %{_libdir}/libctatapereactorutils.so
%attr(0755,root,root) %{_libdir}/libctatapeserverdaemonutils.so
%attr(0644,root,root) %{_sysconfdir}/cta/cta_catalogue_db.conf.example
%package -n cta-systemtests
Summary: CERN Tape Archive: unit and system tests with virtual tape drives
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment