/** * Invoked during commit processing to merge down the write set from each index isolated by this * transactions onto the corresponding unisolated index on the database. This method invoked iff a * transaction has successfully prepared and hence is known to have validated successfully. The * default implementation is a NOP. * * @param revisionTime * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/675" >Flush indices in parallel * during checkpoint to reduce IO latency</a> */ protected void mergeOntoGlobalState(final long revisionTime) { this.revisionTime = revisionTime; // Create tasks to checkpoint the indices. final List<Callable<Void>> tasks = new LinkedList<Callable<Void>>(); { final Iterator<Map.Entry<String, ILocalBTreeView>> itr = indices.entrySet().iterator(); while (itr.hasNext()) { final Map.Entry<String, ILocalBTreeView> entry = itr.next(); final String name = entry.getKey(); final IsolatedFusedView isolated = (IsolatedFusedView) entry.getValue(); tasks.add(new CheckpointIndexTask(name, isolated)); } } /* * Submit checkpoint tasks. * * Note: Method blocks until all tasks are done. */ final List<Future<Void>> futures; try { futures = resourceManager.getLiveJournal().getExecutorService().invokeAll(tasks); } catch (InterruptedException ex) { throw new RuntimeException(ex); } /* * Check Futures for errors. * * Note: Per above, all futures are known to be done. */ for (Future<Void> f : futures) { try { f.get(); } catch (InterruptedException e) { throw new RuntimeException(e); } catch (ExecutionException e) { throw new RuntimeException(e); } } }
/** * par2 is a list of languages. For each language $L and domain $D, attempts to load the resource * $D:lang/$L.lang */ public synchronized void loadLocaleDataFiles(IResourceManager p_135022_1_, List p_135022_2_) { this.field_135032_a.clear(); Iterator var3 = p_135022_2_.iterator(); while (var3.hasNext()) { String var4 = (String) var3.next(); String var5 = String.format("lang/%s.lang", new Object[] {var4}); Iterator var6 = p_135022_1_.getResourceDomains().iterator(); while (var6.hasNext()) { String var7 = (String) var6.next(); try { this.loadLocaleData(p_135022_1_.getAllResources(new ResourceLocation(var7, var5))); } catch (IOException var9) {; } } } this.checkUnicode(); }
/** * @todo This might need to be a full {@link Journal} using {@link BufferMode#Temporary} in order * to have concurrency control for the isolated named indices. This would let us leverage the * existing {@link WriteExecutorService} for handling concurrent operations within a * transaction on the same named _isolated_ resource. There are a lot of issues here, * including the level of concurrency expected for transactions. Also, note that the write set * of the tx is not restart safe, we never force writes to disk, etc. Those are good fits for * the {@link BufferMode#Temporary} {@link BufferMode}. However, it might be nice to do * without having a {@link WriteExecutorService} per transaction, e.g., by placing the named * indices for a transaction within a namespace for that tx. * @todo Rather than creating a distinct {@link TemporaryStore} for each tx and then closing and * deleting the store when the tx completes, just use the temporary store factory. Once there * are no more tx's using a given temporary store it will automatically be finalized and * deleted. However, it is important that we namespace the indices so that different * transactions do not see one another's data. * <p>We can do this just as easily with {@link BufferMode#Temporary}, but {@link * IIndexStore#getTempStore()} would have to be modified. However, that would give us more * concurrency control in the tmp stores and we might need that for concurrent access to named * indices (see above). */ private IRawStore getTemporaryStore() { return resourceManager.getLiveJournal().getTempStore(); // assert lock.isHeldByCurrentThread(); // // if (tmpStore == null) { // // final int offsetBits = resourceManager.getLiveJournal() // .getOffsetBits(); // // tmpStore = new TemporaryRawStore(offsetBits); // // } // // return tmpStore; }
/** * Invoked when a writable transaction prepares in order to validate its write sets (one per * isolated index). The default implementation is NOP. * * @return true iff the write sets were validated. */ protected boolean validateWriteSets() { /* * for all isolated btrees, if(!validate()) return false; */ final Iterator<Map.Entry<String, ILocalBTreeView>> itr = indices.entrySet().iterator(); while (itr.hasNext()) { final Map.Entry<String, ILocalBTreeView> entry = itr.next(); final String name = entry.getKey(); final IsolatedFusedView isolated = (IsolatedFusedView) entry.getValue(); /* * Note: this is the live version of the named index. We need to * validate against the live version of the index, not some * historical state. */ final AbstractBTree[] sources = resourceManager.getIndexSources(name, UNISOLATED); if (sources == null) { log.warn("Index does not exist: " + name); return false; } if (!isolated.validate(sources)) { // Validation failed. if (log.isInfoEnabled()) log.info("validation failed: " + name); return false; } } return true; }
/** * Return a named index. The index will be isolated at the same level as this transaction. Changes * on the index will be made restart-safe iff the transaction successfully commits. * * @param name The name of the index. * @return The named index or <code>null</code> if no index is registered under that name. * @exception IllegalStateException if the transaction is not active. */ public ILocalBTreeView getIndex(final String name) { if (name == null) throw new IllegalArgumentException(); if (readOnly) { /* * Note: Access to the indices currently goes through the * IResourceManager interface for a read-only transaction. */ throw new UnsupportedOperationException(); } /* * @todo lock could be per index for higher concurrency rather than for * all indices which you might access through this tx. */ lock.lock(); try { if (!isActive()) { throw new IllegalStateException(NOT_ACTIVE); } /* * Test the cache - this is used so that we can recover the same * instance on each call within the same transaction. */ if (indices.containsKey(name)) { // Already defined. return indices.get(name); } final ILocalBTreeView index; /* * See if the index was registered as of the ground state used by * this transaction to isolated indices. * * Note: IResourceManager#getIndex(String name,long timestamp) calls * us when the timestamp identifies an active transaction so we MUST * NOT call that method ourselves! Hence there is some replication * of logic between that method and this one. */ final AbstractBTree[] sources = resourceManager.getIndexSources(name, readsOnCommitTime); // startTime); if (sources == null) { /* * The named index was not registered as of the transaction * ground state. */ if (log.isInfoEnabled()) log.info("No such index: " + name + ", startTime=" + startTime); return null; } if (!sources[0].getIndexMetadata().isIsolatable()) { throw new RuntimeException("Not isolatable: " + name); } /* * Isolate the named btree. */ // if (readOnly) { // // assert sources[0].isReadOnly(); // // if (sources.length == 1) { // // index = sources[0]; // // } else { // // index = new FusedView(sources); // // } // // } else { /* * Setup the view. The write set is always the first element in * the view. */ // the view definition. final AbstractBTree[] b = new AbstractBTree[sources.length + 1]; /* * Create the write set on a temporary store. * * Note: The BTree is NOT registered under a name so it can not * be discovered on the temporary store. This is fine since we * hold onto a hard reference to the BTree in [indices]. */ b[0] = BTree.create(getTemporaryStore(), sources[0].getIndexMetadata().clone()); System.arraycopy(sources, 0, b, 1, sources.length); // create view with isolated write set. index = new IsolatedFusedView(-startTime, b); // report event. ResourceManager.isolateIndex(startTime, name); // } indices.put(name, index); return index; } finally { lock.unlock(); } }