44import static com .scalar .db .dataloader .cli .util .CommandLineInputUtils .validatePositiveValue ;
55
66import com .fasterxml .jackson .databind .ObjectMapper ;
7+ import com .scalar .db .api .DistributedTransaction ;
78import com .scalar .db .api .DistributedTransactionAdmin ;
89import com .scalar .db .api .TableMetadata ;
10+ import com .scalar .db .common .CoreError ;
911import com .scalar .db .dataloader .core .DataLoaderError ;
1012import com .scalar .db .dataloader .core .FileFormat ;
13+ import com .scalar .db .dataloader .core .ScalarDbMode ;
1114import com .scalar .db .dataloader .core .dataimport .ImportManager ;
1215import com .scalar .db .dataloader .core .dataimport .ImportOptions ;
1316import com .scalar .db .dataloader .core .dataimport .controlfile .ControlFile ;
@@ -75,12 +78,24 @@ public Integer call() throws Exception {
7578 .prettyPrint (prettyPrint )
7679 .build ();
7780 LogWriterFactory logWriterFactory = createLogWriterFactory (config );
81+ File configFile = new File (configFilePath );
82+ TransactionFactory transactionFactory = TransactionFactory .create (configFile );
83+
84+ // Validate transaction mode configuration before proceeding
85+ validateTransactionMode (transactionFactory );
86+
7887 Map <String , TableMetadata > tableMetadataMap =
79- createTableMetadataMap (controlFile , namespace , tableName );
88+ createTableMetadataMap (controlFile , namespace , tableName , transactionFactory );
8089 try (BufferedReader reader =
8190 Files .newBufferedReader (Paths .get (sourceFilePath ), Charset .defaultCharset ())) {
8291 ImportManager importManager =
83- createImportManager (importOptions , tableMetadataMap , reader , logWriterFactory , config );
92+ createImportManager (
93+ importOptions ,
94+ tableMetadataMap ,
95+ reader ,
96+ logWriterFactory ,
97+ config ,
98+ transactionFactory );
8499 importManager .startImport ();
85100 }
86101 return 0 ;
@@ -101,14 +116,16 @@ private LogWriterFactory createLogWriterFactory(ImportLoggerConfig config) {
101116 * @param controlFile control file
102117 * @param namespace Namespace
103118 * @param tableName Single table name
119+ * @param transactionFactory transaction factory to use
104120 * @return {@code Map<String, TableMetadata>} a table metadata map
105121 * @throws ParameterException if one of the argument values is wrong
106122 */
107123 private Map <String , TableMetadata > createTableMetadataMap (
108- ControlFile controlFile , String namespace , String tableName )
109- throws IOException , TableMetadataException {
110- File configFile = new File (configFilePath );
111- TransactionFactory transactionFactory = TransactionFactory .create (configFile );
124+ ControlFile controlFile ,
125+ String namespace ,
126+ String tableName ,
127+ TransactionFactory transactionFactory )
128+ throws TableMetadataException {
112129 try (DistributedTransactionAdmin transactionAdmin = transactionFactory .getTransactionAdmin ()) {
113130 TableMetadataService tableMetadataService = new TableMetadataService (transactionAdmin );
114131 Map <String , TableMetadata > tableMetadataMap = new HashMap <>();
@@ -135,16 +152,17 @@ private Map<String, TableMetadata> createTableMetadataMap(
135152 * @param reader buffered reader with source data
136153 * @param logWriterFactory log writer factory object
137154 * @param config import logging config
155+ * @param transactionFactory transaction factory to use
138156 * @return ImportManager object
139157 */
140158 private ImportManager createImportManager (
141159 ImportOptions importOptions ,
142160 Map <String , TableMetadata > tableMetadataMap ,
143161 BufferedReader reader ,
144162 LogWriterFactory logWriterFactory ,
145- ImportLoggerConfig config )
163+ ImportLoggerConfig config ,
164+ TransactionFactory transactionFactory )
146165 throws IOException {
147- File configFile = new File (configFilePath );
148166 ImportProcessorFactory importProcessorFactory = new DefaultImportProcessorFactory ();
149167 ImportManager importManager =
150168 new ImportManager (
@@ -153,7 +171,7 @@ private ImportManager createImportManager(
153171 importOptions ,
154172 importProcessorFactory ,
155173 scalarDbMode ,
156- TransactionFactory . create ( configFile ) .getTransactionManager ());
174+ transactionFactory .getTransactionManager ());
157175 if (importOptions .getLogMode ().equals (LogMode .SPLIT_BY_DATA_CHUNK )) {
158176 importManager .addListener (new SplitByDataChunkImportLogger (config , logWriterFactory ));
159177 } else {
@@ -236,6 +254,62 @@ private void validateLogDirectory(String logDirectory) throws ParameterException
236254 }
237255 }
238256
257+ /**
258+ * Validate transaction mode configuration by attempting to start and abort a transaction
259+ *
260+ * @param transactionFactory transaction factory to test
261+ * @throws ParameterException if transaction mode is incompatible with the configured transaction
262+ * manager
263+ */
264+ void validateTransactionMode (TransactionFactory transactionFactory ) {
265+ // Only validate when in TRANSACTION mode
266+ if (scalarDbMode != ScalarDbMode .TRANSACTION ) {
267+ return ;
268+ }
269+
270+ DistributedTransaction transaction = null ;
271+ try {
272+ // Try to start a read only transaction to verify the transaction manager is properly
273+ // configured
274+ transaction = transactionFactory .getTransactionManager ().startReadOnly ();
275+ } catch (Exception e ) {
276+ // Check for specific error about beginning transaction not allowed
277+ if (e .getMessage () != null
278+ && e .getMessage ()
279+ .contains (
280+ CoreError .SINGLE_CRUD_OPERATION_TRANSACTION_BEGINNING_TRANSACTION_NOT_ALLOWED
281+ .buildCode ())) {
282+ throw new ParameterException (
283+ spec .commandLine (),
284+ DataLoaderError .INVALID_TRANSACTION_MODE .buildMessage (
285+ "The current configuration does not support TRANSACTION mode. "
286+ + "Please try with STORAGE mode or check your ScalarDB configuration. "
287+ + "Error: "
288+ + e .getClass ().getSimpleName ()
289+ + " - "
290+ + e .getMessage ()));
291+ }
292+
293+ // Other exceptions - configuration or runtime error
294+ throw new ParameterException (
295+ spec .commandLine (),
296+ DataLoaderError .INVALID_TRANSACTION_MODE .buildMessage (
297+ "Failed to validate transaction mode compatibility. Error: "
298+ + e .getClass ().getSimpleName ()
299+ + " - "
300+ + e .getMessage ()));
301+ } finally {
302+ // Ensure transaction is aborted
303+ if (transaction != null ) {
304+ try {
305+ transaction .abort ();
306+ } catch (Exception ignored ) {
307+ // Ignore errors during cleanup
308+ }
309+ }
310+ }
311+ }
312+
239313 /**
240314 * Generate control file from a valid control file path
241315 *
0 commit comments