use of org.apache.ignite.internal.util.GridLongList in project ignite by apache.
the class PagesList method init.
/**
* @param metaPageId Metadata page ID.
* @param initNew {@code True} if new list if created, {@code false} if should be initialized from metadata.
* @throws IgniteCheckedException If failed.
*/
protected final void init(long metaPageId, boolean initNew) throws IgniteCheckedException {
if (metaPageId != 0L) {
if (initNew) {
init(metaPageId, PagesListMetaIO.VERSIONS.latest());
} else {
Map<Integer, GridLongList> bucketsData = new HashMap<>();
long nextId = metaPageId;
while (nextId != 0) {
final long pageId = nextId;
final long page = acquirePage(pageId);
try {
// No concurrent recycling on init.
long pageAddr = readLock(pageId, page);
assert pageAddr != 0L;
try {
PagesListMetaIO io = PagesListMetaIO.VERSIONS.forPage(pageAddr);
io.getBucketsData(pageAddr, bucketsData);
nextId = io.getNextMetaPageId(pageAddr);
assert nextId != pageId : "Loop detected [next=" + U.hexLong(nextId) + ", cur=" + U.hexLong(pageId) + ']';
} finally {
readUnlock(pageId, page, pageAddr);
}
} finally {
releasePage(pageId, page);
}
}
for (Map.Entry<Integer, GridLongList> e : bucketsData.entrySet()) {
int bucket = e.getKey();
long bucketSize = 0;
Stripe[] old = getBucket(bucket);
assert old == null;
long[] upd = e.getValue().array();
Stripe[] tails = new Stripe[upd.length];
for (int i = 0; i < upd.length; i++) {
long tailId = upd[i];
long prevId = tailId;
int cnt = 0;
while (prevId != 0L) {
final long pageId = prevId;
final long page = acquirePage(pageId);
try {
long pageAddr = readLock(pageId, page);
assert pageAddr != 0L;
try {
PagesListNodeIO io = PagesListNodeIO.VERSIONS.forPage(pageAddr);
cnt += io.getCount(pageAddr);
prevId = io.getPreviousId(pageAddr);
// In reuse bucket the page itself can be used as a free page.
if (isReuseBucket(bucket) && prevId != 0L)
cnt++;
} finally {
readUnlock(pageId, page, pageAddr);
}
} finally {
releasePage(pageId, page);
}
}
Stripe stripe = new Stripe(tailId, cnt == 0);
tails[i] = stripe;
bucketSize += cnt;
}
boolean ok = casBucket(bucket, null, tails);
assert ok;
bucketsSize[bucket].set(bucketSize);
}
}
}
}
use of org.apache.ignite.internal.util.GridLongList in project ignite by apache.
the class HadoopConcurrentHashMultimap method rehashIfNeeded.
/**
* @param fromTbl Table.
*/
private void rehashIfNeeded(AtomicLongArray fromTbl) {
if (fromTbl.length() == Integer.MAX_VALUE)
return;
long keys0 = keys();
if (// New size has to be >= than 3/4 of capacity to rehash.
keys0 < 3 * (fromTbl.length() >>> 2))
return;
if (// Check if someone else have done the job.
fromTbl != newTbl)
return;
if (!state.compareAndSet(State.READING_WRITING, State.REHASHING)) {
// Visiting is allowed, but we will not rehash.
assert state.get() != State.CLOSING;
return;
}
if (fromTbl != newTbl) {
// Double check.
// Switch back.
state(State.REHASHING, State.READING_WRITING);
return;
}
// Calculate new table capacity.
int newLen = fromTbl.length();
do {
newLen <<= 1;
} while (newLen < keys0);
if (// Still more than 3/4.
keys0 >= 3 * (newLen >>> 2))
newLen <<= 1;
// This is our target table for rehashing.
AtomicLongArray toTbl = new AtomicLongArray(newLen);
// Make the new table visible before rehashing.
newTbl = toTbl;
// Rehash.
int newMask = newLen - 1;
long failedMeta = 0;
GridLongList collisions = new GridLongList(16);
for (int i = 0; i < fromTbl.length(); i++) {
// Scan source table.
long meta = fromTbl.get(i);
assert meta != -1;
if (meta == 0) {
// No entry.
failedMeta = 0;
if (// Mark as moved.
!fromTbl.compareAndSet(i, 0, -1))
// Retry.
i--;
continue;
}
do {
// Collect all the collisions before the last one failed to nullify or 0.
collisions.add(meta);
meta = collision(meta);
} while (meta != failedMeta);
do {
// Go from the last to the first to avoid 'in-flight' state for meta entries.
meta = collisions.remove();
int addr = keyHash(meta) & newMask;
for (; ; ) {
// Move meta entry to the new table.
long toCollision = toTbl.get(addr);
collision(meta, toCollision);
if (toTbl.compareAndSet(addr, toCollision, meta))
break;
}
} while (!collisions.isEmpty());
// Here 'meta' will be a root pointer in old table.
if (!fromTbl.compareAndSet(i, meta, -1)) {
// Try to mark as moved.
failedMeta = meta;
// Retry the same address in table because new keys were added.
i--;
} else
failedMeta = 0;
}
// Now old and new tables will be the same again.
oldTbl = toTbl;
state(State.REHASHING, State.READING_WRITING);
}
use of org.apache.ignite.internal.util.GridLongList in project ignite by apache.
the class GridDhtAtomicUpdateRequest method addWriteValue.
/**
* {@inheritDoc}
*/
@Override
public void addWriteValue(KeyCacheObject key, @Nullable CacheObject val, EntryProcessor<Object, Object, Object> entryProcessor, long ttl, long conflictExpireTime, @Nullable GridCacheVersion conflictVer, boolean addPrevVal, @Nullable CacheObject prevVal, long updateCntr) {
assert key.partition() >= 0 : key;
keys.add(key);
if (forceTransformBackups) {
assert entryProcessor != null;
entryProcessors.add(entryProcessor);
} else
vals.add(val);
if (addPrevVal) {
if (prevVals == null)
prevVals = new ArrayList<>();
prevVals.add(prevVal);
}
if (updateCntrs == null)
updateCntrs = new GridLongList();
updateCntrs.add(updateCntr);
// In case there is no conflict, do not create the list.
if (conflictVer != null) {
if (conflictVers == null) {
conflictVers = new ArrayList<>();
for (int i = 0; i < keys.size() - 1; i++) conflictVers.add(null);
}
conflictVers.add(conflictVer);
} else if (conflictVers != null)
conflictVers.add(null);
if (ttl >= 0) {
if (ttls == null) {
ttls = new GridLongList(keys.size());
for (int i = 0; i < keys.size() - 1; i++) ttls.add(CU.TTL_NOT_CHANGED);
}
}
if (ttls != null)
ttls.add(ttl);
if (conflictExpireTime >= 0) {
if (conflictExpireTimes == null) {
conflictExpireTimes = new GridLongList(keys.size());
for (int i = 0; i < keys.size() - 1; i++) conflictExpireTimes.add(CU.EXPIRE_TIME_CALCULATE);
}
}
if (conflictExpireTimes != null)
conflictExpireTimes.add(conflictExpireTime);
}
use of org.apache.ignite.internal.util.GridLongList in project ignite by apache.
the class PagesList method putReuseBag.
/**
* @param pageId Page ID.
* @param page Page pointer.
* @param pageAddr Page address.
* @param io IO.
* @param bag Reuse bag.
* @param bucket Bucket.
* @return {@code true} If succeeded.
* @throws IgniteCheckedException if failed.
*/
@SuppressWarnings("ForLoopReplaceableByForEach")
private boolean putReuseBag(final long pageId, final long page, final long pageAddr, PagesListNodeIO io, ReuseBag bag, int bucket) throws IgniteCheckedException {
assert bag != null : "bag is null";
assert !bag.isEmpty() : "bag is empty";
if (io.getNextId(pageAddr) != 0L)
// Splitted.
return false;
long nextId;
long prevId = pageId;
long prevPage = page;
long prevAddr = pageAddr;
Boolean walPlc = null;
// TODO may be unlock right away and do not keep all these pages locked?
GridLongList locked = null;
try {
while ((nextId = bag.pollFreePage()) != 0L) {
int idx = io.addPage(prevAddr, nextId, pageSize());
if (idx == -1) {
// Attempt to add page failed: the node page is full.
final long nextPage = acquirePage(nextId);
try {
// Page from reuse bag can't be concurrently recycled.
long nextPageAddr = writeLock(nextId, nextPage);
assert nextPageAddr != 0L;
if (locked == null)
locked = new GridLongList(6);
locked.add(nextId);
locked.add(nextPage);
locked.add(nextPageAddr);
setupNextPage(io, prevId, prevAddr, nextId, nextPageAddr);
if (needWalDeltaRecord(prevId, prevPage, walPlc))
wal.log(new PagesListSetNextRecord(grpId, prevId, nextId));
// Here we should never write full page, because it is known to be new.
if (needWalDeltaRecord(nextId, nextPage, FALSE))
wal.log(new PagesListInitNewPageRecord(grpId, nextId, io.getType(), io.getVersion(), nextId, prevId, 0L));
// In reuse bucket the page itself can be used as a free page.
if (isReuseBucket(bucket))
incrementBucketSize(bucket);
// Switch to this new page, which is now a part of our list
// to add the rest of the bag to the new page.
prevAddr = nextPageAddr;
prevId = nextId;
prevPage = nextPage;
// Starting from tis point all wal records are written for reused pages from the bag.
// This mean that we use delta records only.
walPlc = FALSE;
} finally {
releasePage(nextId, nextPage);
}
} else {
// TODO: use single WAL record for bag?
if (needWalDeltaRecord(prevId, prevPage, walPlc))
wal.log(new PagesListAddPageRecord(grpId, prevId, nextId));
incrementBucketSize(bucket);
}
}
} finally {
if (locked != null) {
// We have to update our bucket with the new tail.
updateTail(bucket, pageId, prevId);
// Release write.
for (int i = 0; i < locked.size(); i += 3) writeUnlock(locked.get(i), locked.get(i + 1), locked.get(i + 2), FALSE, true);
}
}
return true;
}
use of org.apache.ignite.internal.util.GridLongList in project ignite by apache.
the class CacheGroupAffinityMessage method createAssigns.
/**
*/
private List<GridLongList> createAssigns(List<List<ClusterNode>> assign0) {
if (assign0 != null) {
List<GridLongList> assigns = new ArrayList<>(assign0.size());
for (int i = 0; i < assign0.size(); i++) {
List<ClusterNode> nodes = assign0.get(i);
GridLongList l = new GridLongList(nodes.size());
for (int n = 0; n < nodes.size(); n++) l.add(nodes.get(n).order());
assigns.add(l);
}
return assigns;
}
return null;
}
Aggregations