protected boolean putInternal(Data key, Data value) {
   throwExceptionIfNull(key);
   throwExceptionIfNull(value);
   Collection<MultiMapRecord> coll = txMap.get(key);
   long recordId = -1;
   long timeout = tx.getTimeoutMillis();
   long ttl = extendTimeout(timeout);
   final MultiMapTransactionLog log;
   if (coll == null) {
     MultiMapResponse response = lockAndGet(key, timeout, ttl);
     if (response == null) {
       throw new ConcurrentModificationException(
           "Transaction couldn't obtain lock " + getThreadId());
     }
     recordId = response.getNextRecordId();
     coll = createCollection(response.getRecordCollection(getNodeEngine()));
     txMap.put(key, coll);
     log = new MultiMapTransactionLog(key, name, ttl, getThreadId());
     tx.addTransactionLog(log);
   } else {
     log = (MultiMapTransactionLog) tx.getTransactionLog(getTxLogKey(key));
   }
   MultiMapRecord record =
       new MultiMapRecord(config.isBinary() ? value : getNodeEngine().toObject(value));
   if (coll.add(record)) {
     if (recordId == -1) {
       recordId = nextId(key);
     }
     record.setRecordId(recordId);
     TxnPutOperation operation = new TxnPutOperation(name, key, value, recordId);
     log.addOperation(operation);
     return true;
   }
   return false;
 }
 protected Object reduce(Map<Integer, Object> map) {
   Collection<Data> list = new LinkedList();
   for (Object obj : map.values()) {
     if (obj == null) {
       continue;
     }
     MultiMapResponse response = (MultiMapResponse) obj;
     Collection<MultiMapRecord> coll = response.getCollection();
     if (coll == null) {
       continue;
     }
     for (MultiMapRecord record : coll) {
       list.add(serializationService.toData(record.getObject()));
     }
   }
   return new PortableCollection(list);
 }
 protected Collection<MultiMapRecord> getInternal(Data key) {
   throwExceptionIfNull(key);
   Collection<MultiMapRecord> coll = txMap.get(key);
   if (coll == null) {
     GetAllOperation operation = new GetAllOperation(name, key);
     operation.setThreadId(ThreadUtil.getThreadId());
     try {
       int partitionId = getNodeEngine().getPartitionService().getPartitionId(key);
       final OperationService operationService = getNodeEngine().getOperationService();
       Future<MultiMapResponse> f =
           operationService.invokeOnPartition(
               MultiMapService.SERVICE_NAME, operation, partitionId);
       MultiMapResponse response = f.get();
       coll = response.getRecordCollection(getNodeEngine());
     } catch (Throwable t) {
       throw ExceptionUtil.rethrow(t);
     }
   }
   return coll;
 }
 protected boolean removeInternal(Data key, Data value) {
   throwExceptionIfNull(key);
   throwExceptionIfNull(value);
   Collection<MultiMapRecord> coll = txMap.get(key);
   long timeout = tx.getTimeoutMillis();
   long ttl = extendTimeout(timeout);
   final MultiMapTransactionLog log;
   if (coll == null) {
     MultiMapResponse response = lockAndGet(key, timeout, ttl);
     if (response == null) {
       throw new ConcurrentModificationException(
           "Transaction couldn't obtain lock " + getThreadId());
     }
     coll = createCollection(response.getRecordCollection(getNodeEngine()));
     txMap.put(key, coll);
     log = new MultiMapTransactionLog(key, name, ttl, getThreadId());
     tx.addTransactionLog(log);
   } else {
     log = (MultiMapTransactionLog) tx.getTransactionLog(getTxLogKey(key));
   }
   MultiMapRecord record =
       new MultiMapRecord(config.isBinary() ? value : getNodeEngine().toObject(value));
   Iterator<MultiMapRecord> iterator = coll.iterator();
   long recordId = -1;
   while (iterator.hasNext()) {
     MultiMapRecord r = iterator.next();
     if (r.equals(record)) {
       iterator.remove();
       recordId = r.getRecordId();
       break;
     }
   }
   if (recordId != -1) {
     TxnRemoveOperation operation = new TxnRemoveOperation(name, key, recordId, value);
     log.addOperation(operation);
     return recordId != -1;
   }
   return false;
 }
 protected Collection<MultiMapRecord> removeAllInternal(Data key) {
   throwExceptionIfNull(key);
   long timeout = tx.getTimeoutMillis();
   long ttl = extendTimeout(timeout);
   Collection<MultiMapRecord> coll = txMap.get(key);
   final MultiMapTransactionLog log;
   if (coll == null) {
     MultiMapResponse response = lockAndGet(key, timeout, ttl);
     if (response == null) {
       throw new ConcurrentModificationException(
           "Transaction couldn't obtain lock " + getThreadId());
     }
     coll = createCollection(response.getRecordCollection(getNodeEngine()));
     log = new MultiMapTransactionLog(key, name, ttl, getThreadId());
     tx.addTransactionLog(log);
   } else {
     log = (MultiMapTransactionLog) tx.getTransactionLog(getTxLogKey(key));
   }
   txMap.put(key, createCollection());
   TxnRemoveAllOperation operation = new TxnRemoveAllOperation(name, key, coll);
   log.addOperation(operation);
   return coll;
 }