2015-05-26 6 views
0

Глядя в ChronicleMap (2.1.7), и я не совсем понимаю правильное использование WriteContext при вызове метода полученияUsingLocked();ChronicleMap Использование WriteContext

Сценарий, который меня интересует, - это функция, в которой мне нужно предпринять 2 действия атомарно с точки зрения вызывающего функции. Один из них добавляет запись на карту, если ее нет. Другой должен иметь место, если ранее не было значения для данного ключа на карте.

Если ранее не было значения для заданного ключа на карте, и это второе действие не удалось, карта не должна обновляться, поэтому последующие тесты не найдут значения для соответствующего ключа.

Если на карте для данного ключа уже есть запись, я не хочу обновлять ее исходное значение, и я не хочу предпринимать это второе действие. Но мне нужно использовать значение исходной записи, чтобы построить возвращаемое значение для вызывающего.

В документации для WriteContext.created() указано, что он возвращает true, только если запись была ранее. Если запись была ранее представлена, возможно ли получить ссылку на предыдущее значение из контекста (или каким-либо другим способом - например, вызов map.get() в пределах области WriteContext)?

С чем связано WriteContext.value()? Значение предыдущей записи или потенциально обновленное значение, указанное мной в вызове purchaseUsingLocked()?

Кроме того, если ранее не было записи на карте, и я не хочу обновлять карту, я должен вызвать WriteContext.removeEntry() или WriteContext.dontPutOnClose()?

Вот пример логики я думаю, мне нужно:

EntryData newValue = new EntryData(); 
    EntryData originalValue = null; 
    try (WriteContext<String, EntryData> context = _map.acquireUsingLocked(key, newValue)) { 
     if (!context.created()) { 
      if (doSomething()) { 
       result = createResult(newValue); 
      } 
      else { 
       context.removeEntry(); 
       result = null; 
      } 
     } 
     else { 
      context.dontPutOnClose(); 
      originalValue = context.value(); 
      result = createResult(originalValue); 
     } 
    } 

ответ

0

Чтобы быть честным, это действительно трудно разобрать ваш вопрос.

Один из них добавляет запись на карту, если ее нет.

Остальное должно иметь место только в том случае, если ранее не было значения для данного ключа на карте.

Я не понимаю разницы. Для меня эти чувства являются синонимическими.


Что WriteContext.value() относится? Значение предыдущей записи или потенциально обновленное значение, указанное мной в вызове purchaseUsingLocked()?

writeContext.value() всегда одинакова (==) до значения, вы предоставили acquireUsingLocked() метод, newValue в вашем примере. Если это невозможно, то забрасывается RuntimeException.

Кроме того, если бы не было ранее запись в карте, и я не хочу, чтобы обновить карту, я должен позвонить WriteContext.removeEntry(), или WriteContext.dontPutOnClose()?

WriteContext.removeEntry(), потому что к моменту возврата acquireUsingLocked() запись уже помещена на карту.


acquireUsingLocked() Метод в ChronicleMap, версия 2.х предназначена для двух типов значений: data value generated и CharSequence, с помощью StringBuilder.

Сгенерированный с помощью данных интерфейс - это указатель на неактивную память. Если acquireUsingLocked() называется, когда не было никакой записи ключа в карте, новая запись создается, заполняется нулями и usingValue, чтобы он указывал кремовый кучу байтов, уже хранящихся на карте:

try (WriteContext<K, LongValue> wc = map.acquireUsingLocked(k, value)) { 
    // update off-heap bytes, already serving as a value for the key 
    // now: k -> LongValue { 0 } 
    value.setValue(42); 
    // now: k -> LongValue { 42 } 
} 

В CharSequence value case, когда acquireUsingLocked() вызывается и не замечает значения для ключа, он помещает пустую последовательность символов в ключ и устанавливает заданное значение StringBuilder в нулевую длину: sb.setLength(0). Вы можете обновить значение в пределах WriteContext, например sb.append("Hello"). Когда вызывается WriteContext.close() (конец блока try-with-resources), это значение sb подбирается и снова помещается для запрошенного ключа на карту. Чтобы предотвратить это, вы можете позвонить dontPutOnClose().


Все вышеперечисленные звуки действительно неудобно, так хроники Карта 3.x вводит новые, когерентные «контексты» паттерна. Он не обновляет карту неявно, каким-либо образом.

try (ExternalMapQueryContext<K, V, ?> cxt = map.queryContext(key)) { 
    cxt.writeLock().lock(); 
    MapEntry<K, V> entry = map.entry(); 
    if (entry != null) { 
     // entry is already present in the map. 
     map.value.get(); // access the _previous_ value; 
     // value is not updated until you call: 
     cxt.replaceValue(entry, cxt.wrapValueAsData(newValue)); 
     // or remove: 
     cxt.remove(entry); 
    } else { 
     // entry is absent. 
     // can insert a value using: 
     cxt.insert(cxt.absentEntry(), cxt.wrapValueAsData(newValue)); 
    } 
} 
// no implicit inserts, removes, updates.