@BeforeClass public static void startTestServer() throws ObjectGridException, FileNotFoundException, IOException, URISyntaxException { utils = WXSUtils.getDefaultUtils(); client = utils.getObjectGrid(); skuMap = utils.getCache(TestMapNames.skuMap); asManager = new AsyncServiceManagerImpl(utils); }
/** * This method searches across multiple indexes and combines the answers. Create the business * object and only initialize the attributes you want to actually use in the query. You can AND or * OR all these attributes. * * @param criteria A business object with only attributes in the query set. Others must be null * @param isAND TRUE if results are to be ANDed otherwise the results are ORed * @return The list of keys for the matching entries @See TestSubstringIndex */ public SearchResult<RK> searchMultipleIndexes(A criteria, boolean isAND) { try { Set<ByteArrayKey> result = null; // first run the individual queries for each attribute in parallel Collection<Future<SearchResult<byte[]>>> threads = new ArrayList<Future<SearchResult<byte[]>>>(); for (Field f : indexedFields) { final String value = (String) f.get(criteria); // non null field means it's in the query if (value != null) { final Index<A, RK> index = getIndex(f.getName()); Callable<SearchResult<byte[]>> c = new Callable<SearchResult<byte[]>>() { public SearchResult<byte[]> call() { SearchResult<byte[]> r = index.rawContains(value); return r; } }; Future<SearchResult<byte[]>> future = utils.getExecutorService().submit(c); threads.add(future); } } // the collect the results and AND/OR them for (Future<SearchResult<byte[]>> future : threads) { SearchResult<byte[]> r = future.get(); if (!r.isTooManyMatches()) { Collection<ByteArrayKey> rr = convertToKeys(r.getResults()); if (result == null) result = new HashSet<ByteArrayKey>(rr); else if (isAND) { // AND this index match with the current running results LinkedList<ByteArrayKey> removeList = new LinkedList<ByteArrayKey>(); for (ByteArrayKey k : rr) { if (!result.contains(k)) removeList.add(k); } for (ByteArrayKey k : result) { if (!rr.contains(k)) removeList.add(k); } result.removeAll(removeList); } else result.addAll(rr); } } if (result != null) { Map<ByteArrayKey, RK> rc = utils.getAll(result, utils.getObjectGrid().getMap(internalKeyToRealKeyMapName)); return new SearchResult<RK>(new ArrayList<RK>(rc.values())); } else return new SearchResult<RK>(); } catch (Exception e) { throw new ObjectGridRuntimeException(e); } }
public Map<K, Boolean> cond_putAll(Map<K, V> originalValues, Map<K, V> newValues) { WXSMapMBeanImpl mbean = WXSUtils.getWXSMapMBeanManager().getBean(grid.getName(), mapName); long start = System.nanoTime(); Map<K, Boolean> rc = utils.cond_putAll(originalValues, newValues, bmap); mbean.getPutMetrics().logTime(System.nanoTime() - start); return rc; }
/** * Fetch all the values for the specified keys. Null is returned if the key isn't found. * * @param keys * @return */ public Map<K, V> getAll(Collection<K> keys) { WXSMapMBeanImpl mbean = WXSUtils.getWXSMapMBeanManager().getBean(grid.getName(), mapName); long start = System.nanoTime(); Map<K, V> rc = utils.getAll(keys, bmap); mbean.getGetMetrics().logTime(System.nanoTime() - start); return rc; }
public Object process(Session sess, ObjectMap headMap, Object key) { if (key instanceof ScalarKey) { ScalarKey sk = (ScalarKey) key; key = sk.getKey(); } AgentMBeanImpl mbean = WXSUtils.getAgentMBeanManager() .getBean(sess.getObjectGrid().getName(), this.getClass().getName()); long startNS = System.nanoTime(); try { ObjectMap itemMap = sess.getMap("list-item-string-long"); ListHead head = (ListHead) headMap.getForUpdate(key); if (head != null) { head = (ListHead) headMap.get(key); head.insertItem(isLeft, value, headMap, itemMap); headMap.update(key, head); } else { // list doesn't exist on disk head = new ListHead((String) key, 1, -1, -1); headMap.insert(key, head); head.insertItem(isLeft, value, headMap, itemMap); headMap.update(key, head); } mbean.getKeysMetric().logTime(System.nanoTime() - startNS); } catch (ObjectGridException e) { mbean.getKeysMetric().logException(e); e.printStackTrace(); throw new ObjectGridRuntimeException(e); } return null; }
@Test public void testShoppingCartFiveItemsOutOfStock() throws Exception { initializeTest(); Map<String, KeyOperator<String>> cartCommand = new HashMap<String, KeyOperator<String>>(); for (int sku = 0; sku < 5; ++sku) { ShoppingCartWorker worker1 = new ShoppingCartWorker(); worker1.quantity = 1; cartCommand.put(Integer.toString(sku), worker1); } Session session = utils.getObjectGrid().getSession(); Future<Map<String, KeyOperatorResult<String>>> rc = asManager.doChainedTransaction(session, TestMapNames.skuMap, cartCommand); while (!rc.isDone()) { Thread.sleep(1000); } Map<String, KeyOperatorResult<String>> results = rc.get(); // 1 false/false, size - 1 true/true boolean failedApplied = false; int unapplied = 0; for (KeyOperatorResult<String> r : results.values()) { if (!r.isApplied() && !r.isUnapplied()) { failedApplied = true; } else if (r.isApplied() && r.isUnapplied()) { unapplied++; } } Assert.assertTrue(failedApplied); Assert.assertEquals(results.size() - 1, unapplied); }
public void testPerformanceSingleThread() throws ObjectGridException, InterruptedException { initializeTest(); Map<String, KeyOperator<String>> cartCommand = new HashMap<String, KeyOperator<String>>(); for (int sku = 1; sku <= 5; ++sku) { ShoppingCartWorker worker1 = new ShoppingCartWorker(); worker1.quantity = 1; cartCommand.put(Integer.toString(sku), worker1); } Session session = utils.getObjectGrid().getSession(); long start = System.currentTimeMillis(); ArrayList<Future<Map<String, KeyOperatorResult<String>>>> futures = new ArrayList<Future<Map<String, KeyOperatorResult<String>>>>(); int maxChains = 1; for (int i = 0; i < maxChains; ++i) { Future<Map<String, KeyOperatorResult<String>>> rc = asManager.doChainedTransaction(session, TestMapNames.skuMap, cartCommand); futures.add(rc); } long phase1 = System.currentTimeMillis(); System.out.println("Waiting"); for (int i = 0; i < maxChains; ++i) { Future<Map<String, KeyOperatorResult<String>>> rc = futures.get(i); while (!rc.isDone()) { Thread.sleep(1); } } long phase2 = System.currentTimeMillis(); double rate = maxChains / ((phase1 - start) / 1000.0); System.out.println("Phase 1 is " + rate); rate = maxChains / ((phase2 - start) / 1000.0); System.out.println("Phase 2 is " + rate); }
/** * Set the value for the key. If the entry doesn't exist then it is inserted otherwise it's * updated. * * @param k * @param v */ public void put(K k, V v) { WXSMapMBeanImpl mbean = WXSUtils.getWXSMapMBeanManager().getBean(grid.getName(), mapName); long start = System.nanoTime(); try { InsertAgent<K, V> a = new InsertAgent<K, V>(); a.doGet = true; a.batch = new TreeMap<K, V>(); a.batch.put(k, v); a.isWriteThrough = true; Object o = tls.getMap(mapName).getAgentManager().callReduceAgent(a, Collections.singletonList(k)); if (o instanceof Boolean) { Boolean b = (Boolean) o; if (!b) { logger.log(Level.SEVERE, "put(K,V) failed"); throw new ObjectGridRuntimeException("put failed"); } } mbean.getPutMetrics().logTime(System.nanoTime() - start); } catch (Exception e) { logger.log(Level.SEVERE, "Exception", e); mbean.getPutMetrics().logException(e); throw new ObjectGridRuntimeException(e); } }
/** * This get an advisory lock on a key. In reality, it inserts a record in a 'lock' map to acquire * ownership of a notional named lock (the name is the key). It will try to acquire the lock for * at least timeoutMs. Once acquired, the lock is permanent until the lock is removed OR evictor * by configuring a default evictor on the lock map. * * @param k The name of the lock * @param value Any value, doesn't matter, typically use a Boolean * @param timeOutMS Desired max wait time for a lock * @return true if lock is acquired. */ public boolean lockPrim(boolean isLock, K k, V value, int timeOutMS) { WXSMapMBeanImpl mbean = WXSUtils.getWXSMapMBeanManager().getBean(grid.getName(), mapName); long start = System.nanoTime(); try { LockAgent<K, V> a = new LockAgent<K, V>(); a.isLock = isLock; a.key = k; a.value = value; a.timeOutMS = timeOutMS; Object o = tls.getMap(mapName).getAgentManager().callReduceAgent(a, Collections.singletonList(k)); if (isLock) mbean.getLockMetrics().logTime(System.nanoTime() - start); else mbean.getUnlockMetrics().logTime(System.nanoTime() - start); if (o instanceof Boolean) { Boolean b = (Boolean) o; return b; } else { String c = isLock ? "lock" : "unlock"; logger.log(Level.SEVERE, c + " failed", o.toString()); throw new ObjectGridRuntimeException(c + " failed"); } } catch (Exception e) { logger.log(Level.SEVERE, "Exception", e); if (isLock) mbean.getLockMetrics().logException(e); else mbean.getUnlockMetrics().logException(e); throw new ObjectGridRuntimeException(e); } }
/** * Remove the entry from the Map * * @param k * @return The last value otherwise null */ public void invalidate(K k) { WXSMapMBeanImpl mbean = WXSUtils.getWXSMapMBeanManager().getBean(grid.getName(), mapName); long start = System.nanoTime(); try { tls.getMap(mapName).invalidate(k, true); mbean.getInvalidateMetrics().logTime(System.nanoTime() - start); } catch (Exception e) { logger.log(Level.SEVERE, "Exception", e); mbean.getInvalidateMetrics().logException(e); throw new ObjectGridRuntimeException(e); } }
/** * Fetch a value from the Map * * @param k * @return */ public V get(K k) { WXSMapMBeanImpl mbean = WXSUtils.getWXSMapMBeanManager().getBean(grid.getName(), mapName); long start = System.nanoTime(); try { V rc = (V) tls.getMap(mapName).get(k); mbean.getGetMetrics().logTime(System.nanoTime() - start); return rc; } catch (Exception e) { logger.log(Level.SEVERE, "Exception", e); mbean.getGetMetrics().logException(e); throw new ObjectGridRuntimeException(e); } }
/** * This is called when a client looks up a key which isn't contained in the grid. The grid then * calls this method to fetch the values for the keys. If a key doesn't exist in the backend then * Loader.KEY_NOT_FOUND is returned. */ @SuppressWarnings("unchecked") public List get(TxID tx, List keys, boolean arg2) throws LoaderException { LoaderMBeanImpl mbean = WXSUtils.getLoaderMBeanManager() .getBean(tx.getSession().getObjectGrid().getName(), mapName); try { mbean.getGetSizeMetrics().logTime(keys.size()); long startNS = System.nanoTime(); // Get a Data instance for these database selects Connection conn = getConnection(tx); // list for the results ArrayList<Object> rc = new ArrayList<Object>(); Iterator<Object> iter = keys.iterator(); ValueHolder v = new ValueHolder(); NamedParameterStatement s = new NamedParameterStatement(conn, selectSQL); // for each key in the list while (iter.hasNext()) { Object keyValue = iter.next(); Object value = null; // wrap with a Key object for purequery if needed if (keyAttributeColumn != null) { v._wxsutil_value = keyValue; copyPojoToStatement(s, v, keyFieldNames, keyFields); } else { copyPojoToStatement(s, keyValue, keyFieldNames, keyFields); } ResultSet rs = s.executeQuery(); if (rs.first()) { value = copyResultSetToPojo(rs, theClass, normalFields); } // if we found the value then add it otherwise add KEY_NOT_FOUND if (value != null) { rc.add(value); if (logger.isLoggable(Level.FINE)) logger.fine("Found " + keyValue + " in " + tableName + " = " + value); } else { rc.add(Loader.KEY_NOT_FOUND); if (logger.isLoggable(Level.FINE)) logger.fine("Cant find " + keyValue + " in " + tableName); } } mbean.getGetMetrics().logTime(System.nanoTime() - startNS); return rc; } catch (Exception e) { logger.log(Level.SEVERE, "Unexpected exception in get", e); mbean.getGetMetrics().logException(e); throw new LoaderException(e); } }
@Test public void testShoppingCartOneItemOutOfStock() throws Exception { initializeTest(); ShoppingCartWorker worker1 = new ShoppingCartWorker(); worker1.quantity = 1; Map<String, KeyOperator<String>> cartCommand = new HashMap<String, KeyOperator<String>>(); cartCommand.put("0", worker1); Session session = utils.getObjectGrid().getSession(); Future<Map<String, KeyOperatorResult<String>>> rc = asManager.doChainedTransaction(session, TestMapNames.skuMap, cartCommand); while (!rc.isDone()) { Thread.sleep(1000); } Map<String, KeyOperatorResult<String>> results = rc.get(); Assert.assertEquals(1, results.size()); KeyOperatorResult<String> r = results.get("0"); // apply returned false, unapply not executed Assert.assertFalse(r.isApplied()); Assert.assertFalse(r.isUnapplied()); }
@Test public void testShoppingCartFiveItems() throws Exception { initializeTest(); Map<String, KeyOperator<String>> cartCommand = new HashMap<String, KeyOperator<String>>(); for (int sku = 1; sku <= 5; ++sku) { ShoppingCartWorker worker1 = new ShoppingCartWorker(); worker1.quantity = 1; cartCommand.put(Integer.toString(sku), worker1); } Session session = utils.getObjectGrid().getSession(); Future<Map<String, KeyOperatorResult<String>>> rc = asManager.doChainedTransaction(session, TestMapNames.skuMap, cartCommand); while (!rc.isDone()) { Thread.sleep(1000); } Map<String, KeyOperatorResult<String>> results = rc.get(); Assert.assertEquals(5, results.size()); for (KeyOperatorResult<String> r : results.values()) { Assert.assertFalse(r.isUnapplied()); Assert.assertTrue(r.isApplied()); } }
/** * This is called to write changes at the end of a transaction or a flush to the backend this * Loader works with which in this case in a database. We use purequery to flush everything in a * single batch statement. Purequery does the POJO attribute to SQL parameter work for us. */ public void batchUpdate(TxID tx, LogSequence ls) throws LoaderException, OptimisticCollisionException { mapName = ls.getMapName(); LoaderMBeanImpl mbean = WXSUtils.getLoaderMBeanManager() .getBean(tx.getSession().getObjectGrid().getName(), ls.getMapName()); mbean.getBatchSizeMetrics().logTime(ls.size()); long startNS = System.nanoTime(); // start a hetero batch. // make empty lists for the objects that are inserted or updated or deleted ArrayList<LogElement> iList = new ArrayList<LogElement>(1000); ArrayList<LogElement> uList = new ArrayList<LogElement>(1000); ArrayList<LogElement> dList = new ArrayList<LogElement>(1000); try { // get the Data instance for this transaction Connection conn = getConnection(tx); // data.startBatch(HeterogeneousBatchKind.heterogeneousModify__); // get the changes in this transaction Iterator<LogElement> iter = ls.getPendingChanges(); // the key object. We may need to wrap primitive POJOs (Long, Integer etc) with a wrapped // with a key attribute for purequery. while (iter.hasNext()) { // get next transaction change LogElement e = iter.next(); switch (e.getType().getCode()) { case LogElement.CODE_INSERT: // add to insert POJO list iList.add(e); break; case LogElement.CODE_UPDATE: uList.add(e); // add to update POJO list break; case LogElement.CODE_DELETE: // add to delete POJO list dList.add(e); break; } } // execute the statements within the batch for each type of operation if (iList.size() > 0) { if (logger.isLoggable(Level.FINE)) logger.fine("Inserting " + ls.getMapName() + " " + iList.toString()); copyPojoListToBatch( conn, insertSQL, iList, normalFields, normalFieldNames, keyFields, keyFieldNames); } if (uList.size() > 0) { if (logger.isLoggable(Level.FINE)) logger.fine("Updating " + ls.getMapName() + " " + uList.toString()); copyPojoListToBatch( conn, updateSQL, uList, normalFields, normalFieldNames, keyFields, keyFieldNames); } if (dList.size() > 0) { if (logger.isLoggable(Level.FINE)) logger.fine("Deleting " + ls.getMapName() + " " + dList.toString()); copyPojoListToBatch( conn, deleteSQL, dList, normalFields, normalFieldNames, keyFields, keyFieldNames); } mbean.recordOperationRows(iList.size(), uList.size(), dList.size()); mbean.getBatchUpdateMetrics().logTime(System.nanoTime() - startNS); } catch (SQLException e) { logger.log(Level.SEVERE, "SQL exception processing changes", e); mbean.getBatchUpdateMetrics().logException(e); throw new LoaderException("Map " + ls.getMapName(), e); } catch (Exception e) { logger.log(Level.SEVERE, "Unexpected exception processing update", e); mbean.getBatchUpdateMetrics().logException(e); throw new LoaderException("Map " + ls.getMapName(), e); } }
/** * Parallel insert all the entries. This does a real insert, not a put (get/update) * * @param batch */ public void insertAll(Map<K, V> batch) { WXSMapMBeanImpl mbean = WXSUtils.getWXSMapMBeanManager().getBean(grid.getName(), mapName); long start = System.nanoTime(); utils.insertAll(batch, bmap); mbean.getInsertMetrics().logTime(System.nanoTime() - start); }
/** * Invalidate all entries with these keys * * @param keys */ public void invalidateAll(Collection<K> keys) { WXSMapMBeanImpl mbean = WXSUtils.getWXSMapMBeanManager().getBean(grid.getName(), mapName); long start = System.nanoTime(); utils.invalidateAll(keys, bmap); mbean.getInvalidateMetrics().logTime(System.nanoTime() - start); }