5
5
*
6
6
* The MIT License
7
7
*
8
- * @copyright Copyright (c) 2017-2023 TileDB, Inc.
8
+ * @copyright Copyright (c) 2017-2024 TileDB, Inc.
9
9
*
10
10
* Permission is hereby granted, free of charge, to any person obtaining a copy
11
11
* of this software and associated documentation files (the "Software"), to deal
30
30
* This file implements class Config.
31
31
*/
32
32
33
+ #include < filesystem>
33
34
#include < fstream>
34
35
#include < iostream>
35
36
#include < sstream>
36
37
37
38
#include " config.h"
39
+ #include " external/include/nlohmann/json.hpp"
38
40
#include " tiledb/common/logger.h"
39
41
#include " tiledb/sm/enums/serialization_type.h"
40
42
#include " tiledb/sm/misc/constants.h"
41
43
#include " tiledb/sm/misc/parse_argument.h"
42
44
45
+ using json = nlohmann::json;
46
+
43
47
using namespace tiledb ::common;
44
48
45
49
namespace {
@@ -60,14 +64,12 @@ bool ignore_default_via_env(const std::string& param) {
60
64
61
65
namespace tiledb ::sm {
62
66
63
- /* * Return a Config error class Status with a given message **/
64
- inline Status Status_ConfigError (const std::string& msg) {
65
- return {" [TileDB::Config] Error" , msg};
66
- }
67
-
68
- void throw_config_exception (const std::string& msg) {
69
- throw StatusException (Status_ConfigError (msg));
70
- }
67
+ class ConfigException : public StatusException {
68
+ public:
69
+ explicit ConfigException (const std::string& msg)
70
+ : StatusException(" Config" , msg) {
71
+ }
72
+ };
71
73
72
74
/* ****************************** */
73
75
/* CONFIG DEFAULTS */
@@ -561,17 +563,56 @@ Config::~Config() = default;
561
563
/* API */
562
564
/* ****************************** */
563
565
566
+ void Config::login () {
567
+ // Retrieve $HOME path
568
+ std::string home_dir;
569
+ #ifdef _WIN32
570
+ home_dir =
571
+ std::string (std::getenv (" HOMEDRIVE" )) + std::string (getenv (" HOMEPATH" ));
572
+ #else
573
+ home_dir = std::string (std::getenv (" HOME" ));
574
+ #endif
575
+
576
+ // For library versions 22 and older, simply parse the local .json file
577
+ if (constants::format_version <= 22 ) {
578
+ // Find and parse the cloud.json file
579
+ std::string file = home_dir + " /.tiledb/cloud.json" ;
580
+ if (!std::filesystem::exists (file)) {
581
+ throw ConfigException (" Cannot login; cloud.json file does not exist." );
582
+ }
583
+ json data = json::parse (std::ifstream (file));
584
+
585
+ // Set the config values that have been saved to the file
586
+ if (data.contains (" api_key" ) &&
587
+ data[" api_key" ].contains (" X-TILEDB-REST-API-KEY" )) {
588
+ throw_if_not_ok (
589
+ set (" rest.token" , data[" api_key" ][" X-TILEDB-REST-API-KEY" ]));
590
+ }
591
+ if (data.contains (" host" )) {
592
+ throw_if_not_ok (set (" rest.server_address" , data[" host" ]));
593
+ }
594
+ if (data.contains (" password" )) {
595
+ throw_if_not_ok (set (" rest.password" , data[" password" ]));
596
+ }
597
+ if (data.contains (" username" )) {
598
+ throw_if_not_ok (set (" rest.username" , data[" username" ]));
599
+ }
600
+ if (data.contains (" verify_ssl" )) {
601
+ throw_if_not_ok (
602
+ set (" vfs.s3.verify_ssl" , data[" verify_ssl" ] ? " true" : " false" ));
603
+ }
604
+ }
605
+ }
606
+
564
607
Status Config::load_from_file (const std::string& filename) {
565
608
// Do nothing if filename is empty
566
- if (filename.empty ())
567
- return LOG_STATUS (
568
- Status_ConfigError ( " Cannot load from file; Invalid filename " ));
609
+ if (filename.empty ()) {
610
+ throw ConfigException ( " Cannot load from file; Invalid filename " );
611
+ }
569
612
570
613
std::ifstream ifs (filename);
571
614
if (!ifs.is_open ()) {
572
- std::stringstream msg;
573
- msg << " Failed to open config file '" << filename << " '" ;
574
- return LOG_STATUS (Status_ConfigError (msg.str ()));
615
+ throw ConfigException (" Failed to open config file '" + filename + " '" );
575
616
}
576
617
577
618
size_t linenum = 0 ;
@@ -592,7 +633,7 @@ Status Config::load_from_file(const std::string& filename) {
592
633
std::stringstream msg;
593
634
msg << " Failed to parse config file '" << filename << " '; " ;
594
635
msg << " Missing parameter value (line: " << linenum << " )" ;
595
- return LOG_STATUS ( Status_ConfigError ( msg.str () ));
636
+ throw ConfigException ( msg.str ());
596
637
}
597
638
598
639
// Parse extra
@@ -601,7 +642,7 @@ Status Config::load_from_file(const std::string& filename) {
601
642
std::stringstream msg;
602
643
msg << " Failed to parse config file '" << filename << " '; " ;
603
644
msg << " Invalid line format (line: " << linenum << " )" ;
604
- return LOG_STATUS ( Status_ConfigError ( msg.str () ));
645
+ throw ConfigException ( msg.str ());
605
646
}
606
647
607
648
// Set param-value pair
@@ -614,15 +655,14 @@ Status Config::load_from_file(const std::string& filename) {
614
655
615
656
Status Config::save_to_file (const std::string& filename) {
616
657
// Do nothing if filename is empty
617
- if (filename.empty ())
618
- return LOG_STATUS (
619
- Status_ConfigError ( " Cannot save to file; Invalid filename " ));
658
+ if (filename.empty ()) {
659
+ throw ConfigException ( " Cannot save to file; Invalid filename " );
660
+ }
620
661
621
662
std::ofstream ofs (filename);
622
663
if (!ofs.is_open ()) {
623
- std::stringstream msg;
624
- msg << " Failed to open config file '" << filename << " ' for writing" ;
625
- return LOG_STATUS (Status_ConfigError (msg.str ()));
664
+ throw ConfigException (
665
+ " Failed to open config file '" + filename + " ' for writing" );
626
666
}
627
667
for (auto & pv : param_values_) {
628
668
if (unserialized_params_.count (pv.first ) != 0 )
@@ -664,7 +704,7 @@ Status Config::get(const std::string& param, T* value, bool* found) const {
664
704
// Parameter found, retrieve value
665
705
auto status = utils::parse::convert (val, value);
666
706
if (!status.ok ()) {
667
- return Status_ConfigError (
707
+ throw ConfigException (
668
708
std::string (" Failed to parse config value '" ) + std::string (val) +
669
709
std::string (" ' for key '" ) + param + " ' due to: " + status.to_string ());
670
710
}
@@ -751,8 +791,7 @@ Status Config::sanity_check(
751
791
RETURN_NOT_OK (utils::parse::convert (value, &v32));
752
792
} else if (param == " config.logging_format" ) {
753
793
if (value != " DEFAULT" && value != " JSON" )
754
- return LOG_STATUS (
755
- Status_ConfigError (" Invalid logging format parameter value" ));
794
+ throw ConfigException (" Invalid logging format parameter value" );
756
795
} else if (param == " sm.allow_separate_attribute_writes" ) {
757
796
RETURN_NOT_OK (utils::parse::convert (value, &v));
758
797
} else if (param == " sm.allow_updates_experimental" ) {
@@ -799,8 +838,7 @@ Status Config::sanity_check(
799
838
RETURN_NOT_OK (utils::parse::convert (value, &v));
800
839
} else if (param == " sm.var_offsets.mode" ) {
801
840
if (value != " bytes" && value != " elements" )
802
- return LOG_STATUS (
803
- Status_ConfigError (" Invalid offsets format parameter value" ));
841
+ throw ConfigException (" Invalid offsets format parameter value" );
804
842
} else if (param == " sm.fragment_info.preload_mbrs" ) {
805
843
RETURN_NOT_OK (utils::parse::convert (value, &v));
806
844
} else if (param == " ssl.verify" ) {
@@ -825,8 +863,7 @@ Status Config::sanity_check(
825
863
RETURN_NOT_OK (utils::parse::convert (value, &v32));
826
864
} else if (param == " vfs.s3.scheme" ) {
827
865
if (value != " http" && value != " https" )
828
- return LOG_STATUS (
829
- Status_ConfigError (" Invalid S3 scheme parameter value" ));
866
+ throw ConfigException (" Invalid S3 scheme parameter value" );
830
867
} else if (param == " vfs.s3.use_virtual_addressing" ) {
831
868
RETURN_NOT_OK (utils::parse::convert (value, &v));
832
869
} else if (param == " vfs.s3.skit_init" ) {
@@ -866,7 +903,7 @@ Status Config::sanity_check(
866
903
(value == " bucket_owner_full_control" ))))) {
867
904
std::stringstream msg;
868
905
msg << " value " << param << " invalid canned acl for " << param;
869
- return Status_Error (msg.str ());
906
+ throw ConfigException (msg.str ());
870
907
}
871
908
}
872
909
@@ -970,7 +1007,7 @@ optional<T> Config::get_internal(const std::string& key) const {
970
1007
if (status.ok ()) {
971
1008
return {converted_value};
972
1009
}
973
- throw_config_exception (
1010
+ throw ConfigException (
974
1011
" Failed to parse config value '" + std::string (value.value ()) +
975
1012
" ' for key '" + key + " '. Reason: " + status.to_string ());
976
1013
}
@@ -988,7 +1025,7 @@ optional<std::string> Config::get_internal_string(
988
1025
}
989
1026
990
1027
if constexpr (must_find_) {
991
- throw_config_exception (" Failed to get config value for key: " + key);
1028
+ throw ConfigException (" Failed to get config value for key: " + key);
992
1029
}
993
1030
return {nullopt};
994
1031
}
0 commit comments