All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tencent.angel.sona.psf.hyperanf.HyperLogLogPlusElement Maven / Gradle / Ivy

/*
 * Tencent is pleased to support the open source community by making Angel available.
 *
 * Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 *
 * https://opensource.org/licenses/Apache-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 *
 */

package com.tencent.angel.sona.psf.hyperanf;
import com.clearspring.analytics.stream.cardinality.CardinalityMergeException;
import com.clearspring.analytics.stream.cardinality.HyperLogLogPlus;
import com.tencent.angel.ps.storage.vector.element.IElement;
import io.netty.buffer.ByteBuf;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

public class HyperLogLogPlusElement implements IElement {

  private HyperLogLogPlus readCounter;
  private HyperLogLogPlus writeCounter;
  private int p, sp;
  private long node;
  private int isActive;
  private Long closeness;


  public HyperLogLogPlusElement(long node, int p, int sp) {
    readCounter = new HyperLogLogPlus(p, sp);
    this.node = node;
    this.p = p;
    this.sp = sp;
    this.isActive = 1;
    this.closeness = 0L;
    long hashed = jenkins(node, System.currentTimeMillis());
    readCounter.offerHashed(hashed);
    writeCounter = readCounter;
  }

  private HyperLogLogPlusElement(long node, int p, int sp,
                                 HyperLogLogPlus readCounter, HyperLogLogPlus writeCounter,
                                 int isActive, long closeness) {
    this.node = node;
    this.p = p;
    this.sp = sp;
    this.readCounter = readCounter;
    this.writeCounter = writeCounter;
    this.isActive = isActive;
    this.closeness = closeness;
  }

  public HyperLogLogPlus getHyperLogLogPlus() {
    return readCounter;
  }

  public boolean isActive() { return isActive > 0; }

  public long getCloseness() { return closeness; }

  public void updateCloseness(long r) {
    long delta = writeCounter.cardinality() - readCounter.cardinality();
    if (delta > 0) {
      this.closeness += r * delta;
      readCounter = writeCounter;
    } else {
      this.isActive = 0;
    }
  }

  public void merge(HyperLogLogPlus other) {
    try {
      writeCounter = (HyperLogLogPlus) writeCounter.merge(other);
    } catch (CardinalityMergeException e) {
      e.printStackTrace();
    }
  }

  @Override
  public void serialize(ByteBuf output) {
    output.writeLong(node);
    output.writeInt(p);
    output.writeInt(sp);
    output.writeInt(isActive);
    output.writeLong(closeness);
    try {
      byte[] bytes = readCounter.getBytes();
      output.writeInt(bytes.length);
      output.writeBytes(bytes);
      bytes = writeCounter.getBytes();
      output.writeInt(bytes.length);
      output.writeBytes(bytes);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  @Override
  public void deserialize(ByteBuf input) {
    node = input.readLong();
    p = input.readInt();
    sp = input.readInt();
    isActive = input.readInt();
    closeness = input.readLong();
    int len = input.readInt();
    byte[] bytes = new byte[len];
    input.readBytes(bytes);
    try {
      readCounter = HyperLogLogPlus.Builder.build(bytes);
    } catch (IOException e) {
      e.printStackTrace();
    }
    len = input.readInt();
    bytes = new byte[len];
    try {
      writeCounter = HyperLogLogPlus.Builder.build(bytes);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  @Override
  public int bufferLen() {
    return 8 + 4 + 4 + 4 + 8 + 4 + readCounter.sizeof() + 4 + writeCounter.sizeof();
  }

  @Override
  public void serialize(DataOutputStream output) throws IOException {
    output.writeLong(node);
    output.writeInt(p);
    output.writeInt(sp);
    output.writeInt(isActive);
    output.writeLong(closeness);
    byte[] bytes = readCounter.getBytes();
    output.writeInt(bytes.length);
    output.writeBytes(new String(bytes));
    bytes = writeCounter.getBytes();
    output.writeInt(bytes.length);
    output.writeBytes(new String(bytes));
  }

  @Override
  public void deserialize(DataInputStream input) throws IOException {
    node = input.readLong();
    p = input.readInt();
    sp = input.readInt();
    isActive = input.readInt();
    closeness = input.readLong();
    int len = input.readInt();
    byte[] bytes = new byte[len];
    input.readFully(bytes);
    readCounter = HyperLogLogPlus.Builder.build(bytes);
    len = input.readInt();
    bytes = new byte[len];
    input.readFully(bytes);
    writeCounter = HyperLogLogPlus.Builder.build(bytes);
  }

  @Override
  public int dataLen() {
    return bufferLen();
  }

  @Override
  public HyperLogLogPlusElement deepClone() {
    try {
      byte[] bytes = readCounter.getBytes();
      HyperLogLogPlus readPlus = HyperLogLogPlus.Builder.build(bytes);
      bytes = writeCounter.getBytes();
      HyperLogLogPlus writePlus = HyperLogLogPlus.Builder.build(bytes);
      return new HyperLogLogPlusElement(node, p, sp, readPlus, writePlus, isActive, closeness);
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }



  /**
   * Function to compute the hash function from node IDs.
   *
   * Taken from the WebGraph framework, specifically the class
   * IntHyperLogLogCounterArray.
   *
   * Note that the `x` parameter is a `Long`, but the function will also work
   * with `Int` values.
   *
   * @param x    the element to hash, i.e. the node ID
   * @param seed the seed to set up internal state.
   * @return the hashed value of `x`
   */
  private long jenkins(long x, long seed) {
    /* Set up the internal state */
    long a = seed + x;
    long b = seed;
    long c = 0x9e3779b97f4a7c13L; /* the golden ratio; an arbitrary value */
    a -= b; a -= c; a ^= (c >>> 43);
    b -= c; b -= a; b ^= (a << 9);
    c -= a; c -= b; c ^= (b >>> 8);
    a -= b; a -= c; a ^= (c >>> 38);
    b -= c; b -= a; b ^= (a << 23);
    c -= a; c -= b; c ^= (b >>> 5);
    a -= b; a -= c; a ^= (c >>> 35);
    b -= c; b -= a; b ^= (a << 49);
    c -= a; c -= b; c ^= (b >>> 11);
    a -= b; a -= c; a ^= (c >>> 12);
    b -= c; b -= a; b ^= (a << 18);
    c -= a; c -= b; c ^= (b >>> 22);
    return c;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy