1313import com .parquet .parquetdataformat .memory .ArrowBufferPool ;
1414import com .parquet .parquetdataformat .writer .ParquetDocumentInput ;
1515import org .apache .arrow .vector .FieldVector ;
16- import org .apache .arrow .vector .types .pojo .Field ;
1716import org .apache .arrow .vector .types .pojo .Schema ;
1817import org .apache .logging .log4j .LogManager ;
1918import org .apache .logging .log4j .Logger ;
3736 * <li>{@link com.parquet.parquetdataformat.bridge.RustBridge} - Direct JNI calls to Rust backend</li>
3837 * </ul>
3938 */
40- public class VSRManager implements Closeable {
39+ public class VSRManager implements AutoCloseable {
40+
41+ private static final Logger logger = LogManager .getLogger (VSRManager .class );
42+
4143 private final AtomicReference <ManagedVSR > managedVSR = new AtomicReference <>();
42- private Map <String , FieldVector > fieldVectorMap ;
4344 private final Schema schema ;
4445 private final String fileName ;
4546 private final VSRPool vsrPool ;
4647 private NativeParquetWriter writer ;
4748
48- private static final Logger logger = LogManager .getLogger (VSRManager .class );
49-
5049
5150 public VSRManager (String fileName , Schema schema , ArrowBufferPool arrowBufferPool ) {
5251 this .fileName = fileName ;
@@ -57,7 +56,7 @@ public VSRManager(String fileName, Schema schema, ArrowBufferPool arrowBufferPoo
5756
5857 // Get active VSR from pool
5958 this .managedVSR .set (vsrPool .getActiveVSR ());
60- initializeFieldVectorMap ();
59+
6160 // Initialize writer lazily to avoid crashes
6261 initializeWriter ();
6362 }
@@ -75,11 +74,7 @@ private void initializeWriter() {
7574 public WriteResult addToManagedVSR (ParquetDocumentInput document ) throws IOException {
7675 ManagedVSR currentVSR = managedVSR .updateAndGet (vsr -> {
7776 if (vsr == null ) {
78- ManagedVSR newVSR = vsrPool .getActiveVSR ();
79- if (newVSR != null ) {
80- reinitializeFieldVectorMap ();
81- }
82- return newVSR ;
77+ return vsrPool .getActiveVSR ();
8378 }
8479 return vsr ;
8580 });
@@ -147,10 +142,29 @@ public void close() {
147142 writer .flush ();
148143 writer .close ();
149144 }
145+
146+ // Close VSR Pool - handle IllegalStateException specially
150147 vsrPool .close ();
151148 managedVSR .set (null );
149+
150+ } catch (IllegalStateException e ) {
151+ // Direct IllegalStateException - re-throw for business logic validation
152+ logger .error ("Error during close for {}: {}" , fileName , e .getMessage (), e );
153+ throw e ;
154+ } catch (RuntimeException e ) {
155+ // Check if this is a wrapped IllegalStateException from defensive cleanup
156+ Throwable cause = e .getCause ();
157+ if (cause instanceof IllegalStateException ) {
158+ // Re-throw the original IllegalStateException for business logic validation
159+ logger .error ("Error during close for {}: {}" , fileName , cause .getMessage (), cause );
160+ throw (IllegalStateException ) cause ;
161+ }
162+ // For other RuntimeExceptions, log and re-throw
163+ logger .error ("Error during close for {}: {}" , fileName , e .getMessage (), e );
164+ throw new RuntimeException ("Failed to close VSRManager: " + e .getMessage (), e );
152165 } catch (Exception e ) {
153166 logger .error ("Error during close for {}: {}" , fileName , e .getMessage (), e );
167+ throw new RuntimeException ("Failed to close VSRManager: " + e .getMessage (), e );
154168 }
155169 }
156170
@@ -199,9 +213,6 @@ public void maybeRotateActiveVSR() throws IOException {
199213 }
200214 updateVSRAndReinitialize (oldVSR , newVSR );
201215
202- // Reinitialize field vector map with new VSR
203- reinitializeFieldVectorMap ();
204-
205216 logger .debug ("VSR rotation completed for {}, new active VSR: {}, row count: {}" ,
206217 fileName , newVSR .getId (), newVSR .getRowCount ());
207218 }
@@ -239,28 +250,7 @@ private void checkAndHandleVSRRotation() throws IOException {
239250 * Atomically updates managedVSR and reinitializes field vector map.
240251 */
241252 private void updateVSRAndReinitialize (ManagedVSR oldVSR , ManagedVSR newVSR ) {
242- if (managedVSR .compareAndSet (oldVSR , newVSR )) {
243- reinitializeFieldVectorMap ();
244- }
245- }
246-
247- /**
248- * Reinitializes the field vector map with the current managed VSR.
249- * Called after VSR rotation to update vector references.
250- */
251- private void reinitializeFieldVectorMap () {
252- fieldVectorMap .clear ();
253- initializeFieldVectorMap ();
254- }
255-
256- private void initializeFieldVectorMap () {
257- fieldVectorMap = new HashMap <>();
258- for (Field field : schema .getFields ()) {
259- String fieldName = field .getName ();
260- FieldVector fieldVector = managedVSR .get ().getVector (fieldName );
261- // Vector is already properly typed from ManagedVSR.getVector()
262- fieldVectorMap .put (fieldName , fieldVector );
263- }
253+ managedVSR .compareAndSet (oldVSR , newVSR );
264254 }
265255
266256 /**
@@ -271,4 +261,13 @@ private void initializeFieldVectorMap() {
271261 public ManagedVSR getActiveManagedVSR () {
272262 return managedVSR .get ();
273263 }
264+
265+ /**
266+ * Gets the current frozen VSR for testing purposes.
267+ *
268+ * @return The current frozen VSR instance, or null if none exists
269+ */
270+ public ManagedVSR getFrozenVSR () {
271+ return vsrPool .getFrozenVSR ();
272+ }
274273}
0 commit comments