public AbstractTransactionHandler(HStoreSite hstore_site, HStoreCoordinator hstore_coord) { this.hstore_site = hstore_site; this.hstore_conf = hstore_site.getHStoreConf(); this.coordinator = hstore_coord; this.handler = this.coordinator.getHandler(); this.num_sites = this.hstore_site.getCatalogContext().numberOfSites; this.local_site_id = hstore_site.getSiteId(); }
/** * Constructor * * @param executor */ public AbstractTransaction(HStoreSite hstore_site) { this.hstore_site = hstore_site; int numPartitions = hstore_site.getCatalogContext().numberOfPartitions; this.released = new boolean[numPartitions]; this.prepared = new boolean[numPartitions]; this.finished = new boolean[numPartitions]; this.round_state = new RoundState[numPartitions]; this.round_ctr = new int[numPartitions]; this.exec_readOnly = new boolean[numPartitions]; this.exec_queueWork = new boolean[numPartitions]; this.exec_eeWork = new boolean[numPartitions]; this.exec_firstUndoToken = new long[numPartitions]; this.exec_lastUndoToken = new long[numPartitions]; this.exec_noUndoBuffer = new boolean[numPartitions]; this.init_task = new InitializeTxnMessage(this); this.readTables = new boolean[numPartitions][]; this.writeTables = new boolean[numPartitions][]; Arrays.fill(this.exec_firstUndoToken, HStoreConstants.NULL_UNDO_LOGGING_TOKEN); Arrays.fill(this.exec_lastUndoToken, HStoreConstants.NULL_UNDO_LOGGING_TOKEN); Arrays.fill(this.exec_readOnly, true); Arrays.fill(this.exec_queueWork, false); Arrays.fill(this.exec_eeWork, false); }
@Override public void run(ClientResponseImpl parameter) { if (debug.get()) LOG.debug( String.format( "Got ClientResponse callback for txn #%d! Sending back to %s", parameter.getTransactionId(), HStoreThreadManager.formatSiteName(this.destSiteId))); FastSerializer fs = new FastSerializer(); try { parameter.writeExternal(fs); } catch (IOException ex) { throw new RuntimeException(ex); } ByteString bs = ByteString.copyFrom(fs.getBuffer()); TransactionRedirectResponse response = TransactionRedirectResponse.newBuilder() .setSenderSite(this.sourceSiteId) .setOutput(bs) .build(); this.orig_callback.run(response); if (debug.get()) LOG.debug( String.format( "Sent back ClientResponse for txn #%d to %s [bytes=%d]", parameter.getTransactionId(), HStoreThreadManager.formatSiteName(this.destSiteId))); // IMPORTANT: Since we're the only one that knows that we're finished (and actually even // cares), we need to be polite and clean-up after ourselves... try { this.finish(); hstore_site.getObjectPools().CALLBACKS_TXN_REDIRECT_RESPONSE.returnObject(this); } catch (Exception ex) { throw new RuntimeException("Funky failure", ex); } }
@Override public void run(TransactionRedirectResponse parameter) { if (LOG.isTraceEnabled()) LOG.trace( String.format( "Got back FORWARD_TXN response from %s. Sending response to client [bytes=%d]", HStoreSite.formatSiteName(parameter.getSenderId()), parameter.getOutput().size())); byte data[] = parameter.getOutput().toByteArray(); try { this.orig_callback.run(data); } catch (Throwable ex) { FastDeserializer fds = new FastDeserializer(data); ClientResponseImpl cresponse = null; long txn_id = -1; try { cresponse = fds.readObject(ClientResponseImpl.class); txn_id = cresponse.getTransactionId(); } catch (IOException e) { LOG.fatal("We're really falling apart here!", e); } LOG.fatal("Failed to forward ClientResponse data back for txn #" + txn_id, ex); // throw ex; } finally { try { this.finish(); HStoreObjectPools.CALLBACKS_TXN_REDIRECT_REQUEST.returnObject(this); } catch (Exception ex) { throw new RuntimeException("Funky failure", ex); } } }
/** * Mark that this txn has executed a modifying query for the tableIds at the given partition. * <B>Note:</B> This is just tracking that we executed a query. It does not necessarily mean that * the query actually changed anything. * * @param partition * @param tableIds */ public final void markTableIdsAsWritten(int partition, int... tableIds) { if (this.writeTables[partition] == null) { this.writeTables[partition] = new boolean[hstore_site.getCatalogContext().numberOfTables + 1]; } for (int id : tableIds) { this.writeTables[partition][id] = true; } // FOR }
public final WorkFragmentMessage getWorkFragmentMessage(WorkFragment fragment) { if (this.work_task == null) { this.work_task = new WorkFragmentMessage[hstore_site.getCatalogContext().numberOfPartitions]; } int partition = fragment.getPartitionId(); if (this.work_task[partition] == null) { this.work_task[partition] = new WorkFragmentMessage(this, fragment); } else { this.work_task[partition].setFragment(fragment); } return (this.work_task[partition]); }
/** * Send a copy of a single message request to the partitions given as input If a partition is * managed by the local HStoreSite, then we will invoke the sendLocal() method. If it is on a * remote HStoreSite, then we will invoke sendRemote(). * * @param ts * @param request * @param callback * @param partitions */ public void sendMessages( LocalTransaction ts, T request, RpcCallback<U> callback, PartitionSet partitions) { // If this flag is true, then we'll invoke the local method // We want to do this *after* we send out all the messages to the remote sites // so that we don't have to wait as long for the responses to come back over the network boolean send_local = false; boolean site_sent[] = new boolean[this.num_sites]; if (debug.val) LOG.debug( String.format( "Sending %s to %d partitions for %s", request.getClass().getSimpleName(), partitions.size(), ts)); for (int partition : partitions.values()) { int dest_site_id = hstore_site.getCatalogContext().getSiteIdForPartitionId(partition); // Skip this HStoreSite if we're already sent it a message if (site_sent[dest_site_id]) continue; if (trace.val) LOG.trace( String.format( "Sending %s message to %s for %s", request.getClass().getSimpleName(), HStoreThreadManager.formatSiteName(dest_site_id), ts)); // Local Partition if (this.local_site_id == dest_site_id) { send_local = true; } // Remote Partition else { HStoreService channel = coordinator.getChannel(dest_site_id); assert (channel != null) : "Invalid partition id '" + partition + "'"; ProtoRpcController controller = this.getProtoRpcController(ts, dest_site_id); assert (controller != null) : "Invalid " + request.getClass().getSimpleName() + " ProtoRpcController for site #" + dest_site_id; this.sendRemote(channel, controller, request, callback); } site_sent[dest_site_id] = true; } // FOR // Optimization: We'll invoke sendLocal() after we have sent out // all of the messages to remote sites if (send_local) this.sendLocal(ts.getTransactionId(), request, partitions, callback); }
@Override protected void setUp() throws Exception { super.setUp(ProjectType.TPCC); addPartitions(NUM_PARTITONS); Site catalog_site = CollectionUtil.first(CatalogUtil.getCluster(catalog).getSites()); assertNotNull(catalog_site); hstore_site = HStore.initialize(catalog_site, HStoreConf.singleton()); for (int p = 0; p < NUM_PARTITONS; p++) { PartitionExecutor site = new MockPartitionExecutor(p, catalog, p_estimator); hstore_site.addPartitionExecutor(p, site); } // FOR this.queue = new TransactionQueueManager(hstore_site); }
@Override public synchronized void run() { final boolean d = debug.get(); final boolean t = trace.get(); if (this.first) { Thread self = Thread.currentThread(); self.setName( HStoreThreadManager.getThreadName(hstore_site, HStoreConstants.THREAD_NAME_HELPER)); hstore_site.getThreadManager().registerProcessingThread(); this.first = false; } if (t) LOG.trace("New invocation of the ExecutionSiteHelper. Let's clean-up some txns!"); this.hstore_site.updateLogging(); for (PartitionExecutor es : this.executors) { // if (t) LOG.trace(String.format("Partition %d has %d finished transactions", // es.partitionId, es.finished_txn_states.size())); // long to_remove = System.currentTimeMillis() - this.txn_expire; int cleaned = 0; // while (es.finished_txn_states.isEmpty() == false && (this.txn_per_round < 0 || // cleaned < this.txn_per_round)) { // AbstractTransaction ts = es.finished_txn_states.peek(); // if (ts.getEE_FinishedTimestamp() < to_remove) { //// if (traceLOG.info(String.format("Want to clean txn #%d [done=%s, // type=%s]", ts.getTransactionId(), ts.getHStoreSiteDone(), ts.getClass().getSimpleName())); // if (ts.isHStoreSite_Finished() == false) break; // // if (t) LOG.trace("Cleaning txn #" + ts.getTransactionId()); // // // es.cleanupTransaction(ts); // es.finished_txn_states.remove(); // cleaned++; // this.total_cleaned++; // } else break; // } // WHILE if (d && cleaned > 0) LOG.debug( String.format( "Cleaned %d TransactionStates at partition %d [total=%d]", cleaned, es.getPartitionId(), this.total_cleaned)); // Only call tick here! // es.tick(); } // FOR // Recompute MarkovGraphs if we have them MarkovGraph m = null; while ((m = this.markovs_to_recompute.poll()) != null) { if (d) LOG.debug( String.format( "Recomputing MarkovGraph for %s [recomputed=%d, hashCode=%d]", m.getProcedure().getName(), m.getRecomputeCount(), m.hashCode())); m.calculateProbabilities(); if (d && m.isValid() == false) { LOG.error("Invalid MarkovGraph after recomputing! Crashing..."); Exception error = new Exception( String.format( "Invalid %s MarkovGraph for after recomputing", m.getProcedure().getName())); this.hstore_site.getCoordinator().shutdownCluster(error); } } // WHILE }
/** * Mark that this txn has executed a modifying query for the Table at the given partition. * <B>Note:</B> This is just tracking that we executed a query. It does not necessarily mean that * the query actually changed anything. * * @param partition * @param catalog_tbl */ public final void markTableAsWritten(int partition, Table catalog_tbl) { if (this.writeTables[partition] == null) { this.writeTables[partition] = new boolean[hstore_site.getCatalogContext().numberOfTables + 1]; } this.writeTables[partition][catalog_tbl.getRelativeIndex()] = true; }