/** * write_state saves the ObjectState in a file named by the type and Uid of the ObjectState. If * the second argument is SHADOW, then the file name is different so that a subsequent * commit_state invocation will rename the file. * * <p>We need to make sure that each entry is written to the next empty location in the log even * if there's already an entry for this tx. */ protected boolean write_state(Uid objUid, String tName, OutputObjectState state, int ft) throws ObjectStoreException { if (tsLogger.logger.isTraceEnabled()) { tsLogger.logger.trace( "ShadowingStore.write_state(" + objUid + ", " + tName + ", " + StateType.stateTypeString(ft) + ")"); } String fname = null; File fd = null; if (tName != null) { int imageSize = (int) state.length(); byte[] uidString = objUid.stringForm().getBytes(); int buffSize = _redzone.length + uidString.length + imageSize + 8; // don't put in endOfLog since we keep overwriting that. RandomAccessFile ofile = null; java.nio.channels.FileLock lock = null; if (imageSize > 0) { TransactionData theLogEntry = getLogName(objUid, tName, buffSize); // always adds entry to log LogInstance theLog = theLogEntry.container; if (theLog == null) throw new ObjectStoreException(); fname = genPathName(theLog.getName(), tName, ft); fd = openAndLock(fname, FileLock.F_WRLCK, true); if (fd == null) { tsLogger.i18NLogger.warn_objectstore_ShadowingStore_18(fname); return false; } boolean setLength = !fd.exists(); try { ofile = new RandomAccessFile(fd, FILE_MODE); if (setLength) { ofile.setLength(_maxFileSize); } else { // may have to resize file if we keep updating this transaction info if (theLog.remaining() < buffSize) { long size = ofile.length() + buffSize - theLog.remaining(); ofile.setLength(size); theLog.resize(size); } } java.nio.ByteBuffer buff = java.nio.ByteBuffer.allocate(buffSize); buff.put(_redzone); buff.putInt(uidString.length); buff.put(uidString); buff.putInt(imageSize); buff.put(state.buffer()); synchronized (_lock) { ofile.seek(theLogEntry.offset); ofile.write(buff.array()); } } catch (SyncFailedException e) { unlockAndClose(fd, ofile); throw new ObjectStoreException( "ShadowingStore::write_state() - write failed to sync for " + fname, e); } catch (FileNotFoundException e) { unlockAndClose(fd, ofile); e.printStackTrace(); throw new ObjectStoreException( "ShadowingStore::write_state() - write failed to locate file " + fname + ": " + e, e); } catch (IOException e) { unlockAndClose(fd, ofile); e.printStackTrace(); throw new ObjectStoreException( "ShadowingStore::write_state() - write failed for " + fname + ": " + e, e); } finally { try { if (lock != null) lock.release(); } catch (IOException ex) { ex.printStackTrace(); } } } if (!unlockAndClose(fd, ofile)) { tsLogger.i18NLogger.warn_objectstore_ShadowingStore_19(fname); } super.addToCache(fname); return true; } else throw new ObjectStoreException( "ShadowStore::write_state - " + tsLogger.i18NLogger.get_objectstore_notypenameuid() + objUid); }
/** * This is a recovery-only method and should not be called during normal execution. As such we * need to load in all of the logs we can find that aren't already loaded (or activated). */ public boolean allObjUids(String tName, InputObjectState state, int match) throws ObjectStoreException { /* * match will always be OS_COMMITTED since that's all we ever write for * the logs. */ // in case of asynchronous removals trigger the purger now. _purger.trigger(); /* * Get a list of logs. Load them in to memory if we aren't already * working on them/it. But we can prune the entry once we're * finished or the memory footprint will grow. We should do this * for all frozen entries eventually too. */ InputObjectState logs = new InputObjectState(); OutputObjectState objUids = new OutputObjectState(); /* * We never call this method except during recovery. As such we shouldn't * need to worry about optimizations such as checking whether or not the * log is in current working memory. */ if (!super.allObjUids(tName, logs, match)) return false; else { /* * Now we have all of the log names let's attach to each one * and locate the committed instances (not deleted.) */ Uid logName = new Uid(Uid.nullUid()); try { do { logName = UidHelper.unpackFrom(logs); if (logName.notEquals(Uid.nullUid())) { /* * Could check to see if log is in current working memory. */ /* * TODO * * First purge the log if we can, but we need to know that * we're not playing with an instance that is being manipulated * from another VM instance. */ ArrayList<InputObjectState> txs = scanLog(logName, tName); if (txs.size() > 0) { for (int i = 0; i < txs.size(); i++) { UidHelper.packInto(txs.get(i).stateUid(), objUids); } } } } while (logName.notEquals(Uid.nullUid())); // remember null terminator UidHelper.packInto(Uid.nullUid(), objUids); state.setBuffer(objUids.buffer()); } catch (final IOException ex) { ex.printStackTrace(); return false; } return true; } }