You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by dp...@apache.org on 2018/10/11 18:59:20 UTC

[ignite-teamcity-bot] branch ignite-9848-load-all-builds updated (0abdf24 -> 4e2b0c4)

This is an automated email from the ASF dual-hosted git repository.

dpavlov pushed a change to branch ignite-9848-load-all-builds
in repository https://gitbox.apache.org/repos/asf/ignite-teamcity-bot.git.


    from 0abdf24  Merge branch 'master' into ignite-9848-load-all-builds
     add 1cdedbf  UI Bug fix, checking if function
     new 2f6585e  Merge branch 'master' into ignite-9848-load-all-builds
     new 4e2b0c4  IGNITE-9848: Compressed fat build development

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/ignite/ci/analysis/MultBuildRunCtx.java |  3 -
 .../org/apache/ignite/ci/jobs/CheckQueueJob.java   |  2 +-
 .../apache/ignite/ci/tcmodel/conf/BuildType.java   | 21 +++++++
 .../org/apache/ignite/ci/tcmodel/result/Build.java | 58 ++++++++++++++-----
 .../ci/teamcity/ignited/BuildRefCompacted.java     |  8 ++-
 .../ci/teamcity/ignited/FatBuildCompacted.java     | 67 ++++++++++++++++++++++
 .../ignited/{BuildRefDao.java => FatBuildDao.java} | 66 ++++++++-------------
 .../ci/teamcity/ignited/IStringCompactor.java      |  8 ++-
 .../ci/teamcity/ignited/ITeamcityIgnited.java      |  9 +++
 .../ci/teamcity/ignited/IgniteStringCompactor.java |  3 +-
 .../ci/teamcity/ignited/TeamcityIgnitedImpl.java   | 12 ++--
 .../org/apache/ignite/ci/util/ObjectInterner.java  |  8 ++-
 .../java/org/apache/ignite/ci/util/XmlUtil.java    | 36 ++++++++----
 ignite-tc-helper-web/src/main/webapp/js/prs-1.0.js |  2 +-
 .../src/main/webapp/js/testfails-2.1.js            |  3 +-
 .../ignited/IgnitedTcInMemoryIntegrationTest.java  | 59 +++++++++++++++++--
 16 files changed, 275 insertions(+), 90 deletions(-)
 copy ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/{BuildRefDao.java => FatBuildDao.java} (54%)


[ignite-teamcity-bot] 01/02: Merge branch 'master' into ignite-9848-load-all-builds

Posted by dp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dpavlov pushed a commit to branch ignite-9848-load-all-builds
in repository https://gitbox.apache.org/repos/asf/ignite-teamcity-bot.git

commit 2f6585e40371de70ecb390f4263fc4d1782fe445
Merge: 0abdf24 1cdedbf
Author: Dmitriy Pavlov <dp...@apache.org>
AuthorDate: Thu Oct 11 21:09:07 2018 +0300

    Merge branch 'master' into ignite-9848-load-all-builds

 ignite-tc-helper-web/src/main/webapp/js/prs-1.0.js       | 2 +-
 ignite-tc-helper-web/src/main/webapp/js/testfails-2.1.js | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)


[ignite-teamcity-bot] 02/02: IGNITE-9848: Compressed fat build development

Posted by dp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dpavlov pushed a commit to branch ignite-9848-load-all-builds
in repository https://gitbox.apache.org/repos/asf/ignite-teamcity-bot.git

commit 4e2b0c46b5a2b2683c11fec49283dd274fe48c59
Author: Dmitriy Pavlov <dp...@apache.org>
AuthorDate: Thu Oct 11 21:59:01 2018 +0300

    IGNITE-9848: Compressed fat build development
---
 .../apache/ignite/ci/analysis/MultBuildRunCtx.java |   3 -
 .../org/apache/ignite/ci/jobs/CheckQueueJob.java   |   2 +-
 .../apache/ignite/ci/tcmodel/conf/BuildType.java   |  21 +++++
 .../org/apache/ignite/ci/tcmodel/result/Build.java |  58 +++++++++---
 .../ci/teamcity/ignited/BuildRefCompacted.java     |   8 +-
 .../ci/teamcity/ignited/FatBuildCompacted.java     |  67 +++++++++++++
 .../ignite/ci/teamcity/ignited/FatBuildDao.java    | 105 +++++++++++++++++++++
 .../ci/teamcity/ignited/IStringCompactor.java      |   8 +-
 .../ci/teamcity/ignited/ITeamcityIgnited.java      |   9 ++
 .../ci/teamcity/ignited/IgniteStringCompactor.java |   3 +-
 .../ci/teamcity/ignited/TeamcityIgnitedImpl.java   |  12 +--
 .../org/apache/ignite/ci/util/ObjectInterner.java  |   8 +-
 .../java/org/apache/ignite/ci/util/XmlUtil.java    |  36 ++++---
 .../ignited/IgnitedTcInMemoryIntegrationTest.java  |  59 +++++++++++-
 14 files changed, 354 insertions(+), 45 deletions(-)

diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java
index 6a338a8..29ecc76 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java
@@ -75,9 +75,6 @@ public class MultBuildRunCtx implements ISuiteResults {
         builds.add(ctx);
     }
 
-    /** Thread dump short file name */
-    @Nullable private Integer threadDumpFileIdx;
-
     /** Currently running builds */
     @Nullable private CompletableFuture<Long> runningBuildCount;
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jobs/CheckQueueJob.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jobs/CheckQueueJob.java
index f1cdf72..e5733d7 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jobs/CheckQueueJob.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jobs/CheckQueueJob.java
@@ -165,7 +165,7 @@ public class CheckQueueJob implements Runnable {
         int running = 0;
 
         for (Agent agent : agents) {
-            if (agent.getBuild() != null) //  || !STATE_RUNNING.equals(agent.getBuild().status)
+            if (agent.getBuild() != null) //  || !STATE_RUNNING.equals(agent.getFatBuild().status)
                 ++running;
         }
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/BuildType.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/BuildType.java
index a7998a6..234b441 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/BuildType.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/BuildType.java
@@ -48,4 +48,25 @@ public class BuildType {
     public String getProjectId() {
         return projectId;
     }
+
+    /**
+     * @param id New id.
+     */
+    public void id(String id) {
+        this.id = id;
+    }
+
+    /**
+     * @param name Name.
+     */
+    public void name(String name) {
+        this.name = name;
+    }
+
+    /**
+     * @param projectId Project id.
+     */
+    public void projectId(String projectId) {
+        this.projectId = projectId;
+    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/Build.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/Build.java
index 443610c..fc43474 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/Build.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/Build.java
@@ -28,13 +28,17 @@ import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
 import org.apache.ignite.ci.analysis.IVersionedEntity;
 import org.apache.ignite.ci.tcmodel.changes.ChangesList;
 import org.apache.ignite.ci.tcmodel.changes.ChangesListRef;
 import org.apache.ignite.ci.tcmodel.conf.BuildType;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
+import org.apache.ignite.ci.util.ExceptionUtil;
 import org.jetbrains.annotations.NotNull;
 
+import static org.apache.ignite.ci.util.ExceptionUtil.propagateException;
+
 /**
  * Build from history with test and problems references
  */
@@ -42,11 +46,16 @@ import org.jetbrains.annotations.NotNull;
 @XmlAccessorType(XmlAccessType.FIELD)
 public class Build extends BuildRef implements IVersionedEntity {
     public static final int LATEST_VERSION = 2;
-    @XmlElement(name = "buildType") BuildType buildType;
+
+    /** Format local. */
+    @XmlTransient private static ThreadLocal<SimpleDateFormat> fmtLoc
+        = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"));
+
+    @XmlElement(name = "buildType") private BuildType buildType;
 
     @XmlElement public String queuedDate;
-    @XmlElement public String startDate;
-    @XmlElement public String finishDate;
+    @XmlElement private String startDate;
+    @XmlElement private String finishDate;
 
     @XmlElement(name = "build")
     @XmlElementWrapper(name = "snapshot-dependencies")
@@ -69,6 +78,7 @@ public class Build extends BuildRef implements IVersionedEntity {
     /** Information about build triggering. */
     @XmlElement(name = "triggered") private Triggered triggered;
 
+    @XmlTransient
     @SuppressWarnings("FieldCanBeLocal") public Integer _version = LATEST_VERSION;
 
     @NotNull public static Build createFakeStub() {
@@ -83,28 +93,43 @@ public class Build extends BuildRef implements IVersionedEntity {
         return buildType == null ? null : buildType.getName();
     }
 
-    public String getFinishDateDdMmYyyy() {
-        Date parse = getFinishDate();
-        return new SimpleDateFormat("dd.MM.yyyy").format(parse);
-    }
-
+    /**
+     *
+     */
     public Date getFinishDate() {
         return getDate(finishDate);
     }
 
+    /**
+     *
+     */
     public Date getStartDate() {
         return getDate(startDate);
     }
 
+    /**
+     * @param ts Timestamp.
+     */
+    public void setStartDateTs(long ts) {
+        startDate = ts < 0 ? null : fmtLoc.get().format(new Date(ts));
+    }
+
+    /**
+     * @param ts Timestamp.
+     */
+    public void setFinishDateTs(long ts) {
+        finishDate = ts < 0 ? null : fmtLoc.get().format(new Date(ts));
+    }
+
+    /**
+     * @param date Date as string.
+     */
     private Date getDate(String date) {
         try {
-            if (date == null)
-                return null;
-            SimpleDateFormat f = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ");
-            return f.parse(date);
+            return date == null ? null : fmtLoc.get().parse(date);
         }
         catch (ParseException e) {
-            throw new IllegalStateException(e);
+            throw propagateException(e);
         }
     }
 
@@ -137,4 +162,11 @@ public class Build extends BuildRef implements IVersionedEntity {
     public void setTriggered(Triggered triggered) {
         this.triggered = triggered;
     }
+
+    /**
+     * @param type Type.
+     */
+    public void setBuildType(BuildType type) {
+        buildType = type;
+    }
 }
\ No newline at end of file
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefCompacted.java
index 77eec6d..3becbe4 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefCompacted.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefCompacted.java
@@ -61,13 +61,17 @@ public class BuildRefCompacted {
     public BuildRef toBuildRef(IStringCompactor compactor) {
         BuildRef res = new BuildRef();
 
+        fillBuildRefFields(compactor, res);
+
+        return res;
+    }
+
+    protected void fillBuildRefFields(IStringCompactor compactor, BuildRef res) {
         res.setId(id < 0 ? null : id);
         res.buildTypeId = compactor.getStringFromId(buildTypeId);
         res.branchName = compactor.getStringFromId(branchName);
         res.status = compactor.getStringFromId(status);
         res.state = compactor.getStringFromId(state);
-
-        return res;
     }
 
     /** {@inheritDoc} */
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/FatBuildCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/FatBuildCompacted.java
index 10fd975..7254abe 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/FatBuildCompacted.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/FatBuildCompacted.java
@@ -18,6 +18,9 @@ package org.apache.ignite.ci.teamcity.ignited;
 
 import org.apache.ignite.ci.analysis.IVersionedEntity;
 import org.apache.ignite.ci.db.Persisted;
+import org.apache.ignite.ci.tcmodel.conf.BuildType;
+import org.apache.ignite.ci.tcmodel.hist.BuildRef;
+import org.apache.ignite.ci.tcmodel.result.Build;
 
 /**
  *
@@ -30,6 +33,15 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
     /** Entity fields version. */
     private short _ver;
 
+    /** Start date. The number of milliseconds since January 1, 1970, 00:00:00 GMT */
+    private long startDate;
+
+    /** Finish date. The number of milliseconds since January 1, 1970, 00:00:00 GMT */
+    private long finishDate;
+
+    private int projectId = -1;
+    private int name = -1;
+
     /** {@inheritDoc} */
     @Override public int version() {
         return _ver;
@@ -39,4 +51,59 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
     @Override public int latestVersion() {
         return LATEST_VERSION;
     }
+
+    /**
+     * Default constructor.
+     */
+    public FatBuildCompacted() {
+    }
+
+    /**
+     * @param compactor Compactor.
+     * @param ref Reference.
+     */
+    public FatBuildCompacted(IStringCompactor compactor, Build ref) {
+        super(compactor, ref);
+
+        startDate = ref.getStartDate() == null ? -1L : ref.getStartDate().getTime();
+        finishDate = ref.getFinishDate() == null ? -1L : ref.getFinishDate().getTime();
+
+        BuildType type = ref.getBuildType();
+        if (type != null) {
+            projectId = compactor.getStringId(type.getProjectId());
+            name = compactor.getStringId(type.getName());
+        }
+    }
+
+    /**
+     * @param compactor Compacter.
+     */
+    public Build toBuild(IStringCompactor compactor) {
+        Build res = new Build();
+
+        fillBuildRefFields(compactor, res);
+
+        fillBuildFields(compactor, res);
+
+        return res;
+    }
+
+    /**
+     * @param compactor Compactor.
+     * @param res Response.
+     */
+    private void fillBuildFields(IStringCompactor compactor, Build res) {
+        if (startDate > 0)
+            res.setStartDateTs(startDate);
+
+        if (finishDate > 0)
+            res.setFinishDateTs(finishDate);
+
+        BuildType type = new BuildType();
+        type.id(res.buildTypeId());
+        type.name(compactor.getStringFromId(name));
+        type.projectId(compactor.getStringFromId(projectId));
+        res.setBuildType(type);
+    }
+
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/FatBuildDao.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/FatBuildDao.java
new file mode 100644
index 0000000..e0706d1
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/FatBuildDao.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://www.apache.org/licenses/LICENSE-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 org.apache.ignite.ci.teamcity.ignited;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.ci.db.TcHelperDb;
+import org.apache.ignite.ci.tcmodel.hist.BuildRef;
+import org.apache.ignite.ci.tcmodel.result.Build;
+import org.apache.ignite.configuration.CacheConfiguration;
+
+/**
+ *
+ */
+public class FatBuildDao {
+    /** Cache name */
+    public static final String TEAMCITY_FAT_BUILD_CACHE_NAME = "teamcityFatBuild";
+
+    /** Ignite provider. */
+    @Inject private Provider<Ignite> igniteProvider;
+
+    /** Builds cache. */
+    private IgniteCache<Long, FatBuildCompacted> buildsCache;
+
+    /** Compactor. */
+    @Inject private IStringCompactor compactor;
+
+    /**
+     *
+     */
+    public void init() {
+        buildsCache = igniteProvider.get().getOrCreateCache(TcHelperDb.getCacheV2Config(TEAMCITY_FAT_BUILD_CACHE_NAME));
+    }
+
+    /**
+     * @param srvIdMaskHigh Server id mask high.
+     * @param ghData Gh data.
+     */
+    public int saveChunk(long srvIdMaskHigh, List<Build> ghData) {
+        Set<Long> ids = ghData.stream().map(BuildRef::getId)
+            .filter(Objects::nonNull)
+            .map(buildId -> buildIdToCacheKey(srvIdMaskHigh, buildId))
+            .collect(Collectors.toSet());
+
+        Map<Long, FatBuildCompacted> existingEntries = buildsCache.getAll(ids);
+        Map<Long, FatBuildCompacted> entriesToPut = new TreeMap<>();
+
+        List<FatBuildCompacted> collect = ghData.stream()
+            .map(ref -> new FatBuildCompacted(compactor, ref))
+            .collect(Collectors.toList());
+
+        for (FatBuildCompacted next : collect) {
+            long cacheKey = buildIdToCacheKey(srvIdMaskHigh, next.id());
+            FatBuildCompacted buildPersisted = existingEntries.get(cacheKey);
+
+            if (buildPersisted == null || !buildPersisted.equals(next))
+                entriesToPut.put(cacheKey, next);
+        }
+
+        int size = entriesToPut.size();
+        if (size != 0)
+            buildsCache.putAll(entriesToPut);
+
+        return size;
+    }
+
+    /**
+     * @param srvIdMaskHigh Server id mask high.
+     * @param buildId Build id.
+     */
+    private long buildIdToCacheKey(long srvIdMaskHigh, int buildId) {
+        return (long)buildId | srvIdMaskHigh << 32;
+    }
+
+    /**
+     * @param srvIdMaskHigh Server id mask high.
+     * @param buildId Build id.
+     */
+    public FatBuildCompacted getFatBuild(int srvIdMaskHigh, int buildId) {
+        return buildsCache.get(buildIdToCacheKey(srvIdMaskHigh, buildId));
+    }
+}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/IStringCompactor.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/IStringCompactor.java
index 59c2986..0ab6d96 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/IStringCompactor.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/IStringCompactor.java
@@ -16,6 +16,9 @@
  */
 package org.apache.ignite.ci.teamcity.ignited;
 
+/**
+ *
+ */
 public interface IStringCompactor {
     /**
      * @param val Value.
@@ -27,5 +30,8 @@ public interface IStringCompactor {
      */
     public String getStringFromId(int id);
 
-    public Integer getStringIdIfPresent(String id);
+    /**
+     * @param val Id.
+     */
+    public Integer getStringIdIfPresent(String val);
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
index 470d5d1..cfba852 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
@@ -48,4 +48,13 @@ public interface ITeamcityIgnited {
      * @param queueAtTop Put at the top of the build queue.
      */
     public Build triggerBuild(String buildTypeId, String branchName, boolean cleanRebuild, boolean queueAtTop);
+
+
+    /**
+     * @param srvId Server id.
+     * @return integer representation of server ID.
+     */
+    public static int serverIdToInt(String srvId) {
+        return Math.abs(srvId.hashCode());
+    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/IgniteStringCompactor.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/IgniteStringCompactor.java
index 5cd2a0b..906b0d5 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/IgniteStringCompactor.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/IgniteStringCompactor.java
@@ -34,6 +34,7 @@ import org.apache.ignite.cache.query.SqlQuery;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.ci.di.AutoProfiling;
 import org.apache.ignite.ci.util.ExceptionUtil;
+import org.apache.ignite.ci.util.ObjectInterner;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.jetbrains.annotations.NotNull;
 
@@ -147,7 +148,7 @@ public class IgniteStringCompactor implements IStringCompactor {
 
         qryCursor.close();
 
-        return next.getValue().val;
+        return ObjectInterner.internString(next.getValue().val);
     }
 
     /** {@inheritDoc} */
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
index 746ef38..d8b295d 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
@@ -36,10 +36,10 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
     /** Pure HTTP Connection API. */
     private ITeamcityConn conn;
 
-
     /** Scheduler. */
     @Inject private IScheduler scheduler;
 
+    /** Build reference DAO. */
     @Inject private BuildRefDao buildRefDao;
 
     /** Server ID mask for cache Entries. */
@@ -50,7 +50,7 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
         this.srvId = srvId;
         this.conn = conn;
 
-        srvIdMaskHigh = Math.abs(srvId.hashCode());
+        srvIdMaskHigh = ITeamcityIgnited.serverIdToInt(srvId);
         buildRefDao.init(); //todo init somehow in auto
     }
 
@@ -81,7 +81,7 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
         Build build = conn.triggerBuild(buildTypeId, branchName, cleanRebuild, queueAtTop);
 
         //todo may add additional parameter: load builds into DB in sync/async fashion
-        runAсtualizeBuilds(srvId, false, build.getId());
+        runActializeBuildRefs(srvId, false, build.getId());
 
         return build;
     }
@@ -90,7 +90,7 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
      *
      */
     private void actualizeRecentBuilds() {
-        runAсtualizeBuilds(srvId, false, null);
+        runActializeBuildRefs(srvId, false, null);
 
         // schedule full resync later
         scheduler.invokeLater(this::sheduleResync, 60, TimeUnit.SECONDS);
@@ -108,7 +108,7 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
      *
      */
     private void fullReindex() {
-        runAсtualizeBuilds(srvId, true, null);
+        runActializeBuildRefs(srvId, true, null);
     }
 
     /**
@@ -118,7 +118,7 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
      */
     @MonitoredTask(name = "Actualize BuildRefs, full resync", nameExtArgIndex = 1)
     @AutoProfiling
-    protected String runAсtualizeBuilds(String srvId, boolean fullReindex,
+    protected String runActializeBuildRefs(String srvId, boolean fullReindex,
         @Nullable Integer buildIdCanFinish) {
         AtomicReference<String> outLinkNext = new AtomicReference<>();
         List<BuildRef> tcDataFirstPage = conn.getBuildRefs(null, outLinkNext);
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/ObjectInterner.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/ObjectInterner.java
index b58fe96..9834d5c 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/ObjectInterner.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/ObjectInterner.java
@@ -32,6 +32,7 @@ import java.util.concurrent.atomic.AtomicInteger;
  * Class with util method for custom strings deduplication (intern analogue).
  */
 public class ObjectInterner {
+    /** String cache. */
     private static final LoadingCache<String, String> stringCache
         = CacheBuilder
         .<String, String>newBuilder()
@@ -39,13 +40,16 @@ public class ObjectInterner {
         .initialCapacity(67537)
         .build(
             new CacheLoader<String, String>() {
-                @Override public String load(String key) throws Exception {
+                @Override public String load(String key) {
                     return key;
                 }
             }
         );
 
-    private static String internString(String str) {
+    /**
+     * @param str String.
+     */
+    public static String internString(String str) {
         if (str == null)
             return null;
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/XmlUtil.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/XmlUtil.java
index 5eb1510..e1e058a 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/XmlUtil.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/XmlUtil.java
@@ -18,9 +18,11 @@
 package org.apache.ignite.ci.util;
 
 import java.io.Reader;
+import java.io.StringWriter;
 import java.util.concurrent.ConcurrentHashMap;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
 
 /**
@@ -31,24 +33,34 @@ public class XmlUtil {
     private static ConcurrentHashMap<Class, JAXBContext> cachedCtx = new ConcurrentHashMap<>();
 
     public static <T> T load(Class<T> tCls, Reader reader) throws JAXBException {
-        final JAXBContext ctx = cachedCtx.computeIfAbsent(tCls, c -> {
-            try {
-                return JAXBContext.newInstance(tCls);
-            }
-            catch (JAXBException e) {
-                throw new RuntimeException(e);
-            }
-        });
-        Unmarshaller unmarshaller = ctx.createUnmarshaller();
+        Unmarshaller unmarshaller = getContext(tCls).createUnmarshaller();
         T unmarshal = (T)unmarshaller.unmarshal(reader);
 
-        int interned = ObjectInterner.internFields(unmarshal);
-       // if (interned > 0)
-       //     System.out.println("Strings saved: " + interned);
+        ObjectInterner.internFields(unmarshal);
 
         return unmarshal;
     }
 
+    public static String save(Object obj) throws JAXBException {
+        Marshaller marshaller = getContext(obj.getClass()).createMarshaller();
+        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+        StringWriter writer = new StringWriter();
+        marshaller.marshal(obj, writer);
+
+        return writer.toString();
+    }
+
+    private static <T> JAXBContext getContext(Class<T> tCls) {
+        return cachedCtx.computeIfAbsent(tCls, c -> {
+                try {
+                    return JAXBContext.newInstance(tCls);
+                }
+                catch (JAXBException e) {
+                    throw new RuntimeException(e);
+                }
+            });
+    }
+
     /**
      * @param t Text to process.
      */
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
index 0cd34d5..7a7809e 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
@@ -20,15 +20,24 @@ import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Collections;
 import java.util.List;
+import javax.xml.bind.JAXBException;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.ci.di.scheduler.DirectExecNoWaitSheduler;
 import org.apache.ignite.ci.di.scheduler.IScheduler;
+import org.apache.ignite.ci.tcmodel.conf.BuildType;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
+import org.apache.ignite.ci.tcmodel.result.Build;
 import org.apache.ignite.ci.teamcity.pure.ITeamcityHttpConnection;
 import org.apache.ignite.ci.user.ICredentialsProv;
+import org.apache.ignite.ci.util.XmlUtil;
 import org.jetbrains.annotations.NotNull;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -54,16 +63,15 @@ public class IgnitedTcInMemoryIntegrationTest {
      *
      */
     @BeforeClass
-    public static void startIgnite(){
+    public static void startIgnite() {
         ignite = Ignition.start();
     }
 
-
     /**
      *
      */
     @AfterClass
-    public static void stopIgnite(){
+    public static void stopIgnite() {
         ignite.close();
     }
 
@@ -72,7 +80,7 @@ public class IgnitedTcInMemoryIntegrationTest {
         ITeamcityHttpConnection http = Mockito.mock(ITeamcityHttpConnection.class);
 
         when(http.sendGet(anyString(), anyString())).thenAnswer(
-            (invocationOnMock)->{
+            (invocationOnMock) -> {
                 String url = invocationOnMock.getArgument(1);
 
                 if (url.contains("/app/rest/latest/builds?locator=defaultFilter:false,count:1000,start:1000"))
@@ -132,4 +140,47 @@ public class IgnitedTcInMemoryIntegrationTest {
 
         return mock;
     }
+
+    @Test
+    public void testFatBuild() throws JAXBException, IOException {
+        InputStream stream = getClass().getResourceAsStream("/build.xml");
+        Build refBuild = XmlUtil.load(Build.class, new InputStreamReader(stream));
+        Injector injector = Guice.createInjector(new AbstractModule() {
+            @Override protected void configure() {
+                bind(Ignite.class).toInstance(ignite);
+                bind(IStringCompactor.class).to(IgniteStringCompactor.class);
+            }
+        });
+
+        FatBuildDao instance = injector.getInstance(FatBuildDao.class);
+        instance.init();
+
+        int srvIdMaskHigh = ITeamcityIgnited.serverIdToInt(APACHE);
+        int i = instance.saveChunk(srvIdMaskHigh, Collections.singletonList(refBuild));
+        assertEquals(1, i);
+
+        FatBuildCompacted fatBuild = instance.getFatBuild(srvIdMaskHigh, 2039380);
+
+        Build actBuild = fatBuild.toBuild(injector.getInstance(IStringCompactor.class));
+
+        String save = XmlUtil.save(actBuild);
+
+        System.out.println(save);
+
+        FileWriter writer = new FileWriter("src/test/resources/build2.xml");
+        writer.write(save);
+        writer.close();
+
+        assertEquals(refBuild.getId(), actBuild.getId());
+        assertEquals(refBuild.status(), actBuild.status());
+        assertEquals(refBuild.state(), actBuild.state());
+        assertEquals(refBuild.buildTypeId(), actBuild.buildTypeId());
+        assertEquals(refBuild.getStartDate(), actBuild.getStartDate());
+        assertEquals(refBuild.getFinishDate(), actBuild.getFinishDate());
+        BuildType refBt = refBuild.getBuildType();
+        BuildType actBt = actBuild.getBuildType();
+        assertEquals(refBt.getName(), actBt.getName());
+        assertEquals(refBt.getProjectId(), actBt.getProjectId());
+        assertEquals(refBt.getId(), actBt.getId());
+    }
 }