{"action":"created","comment":{"url":"https://api.github.com/repos/VoltDB/voltdb/pulls/comments/53673082","id":53673082,"diff_hunk":"@@ -0,0 +1,466 @@\n+/* This file is part of VoltDB.\n+ * Copyright (C) 2008-2016 VoltDB Inc.\n+ *\n+ * This program is free software: you can redistribute it and/or modify\n+ * it under the terms of the GNU Affero General Public License as\n+ * published by the Free Software Foundation, either version 3 of the\n+ * License, or (at your option) any later version.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+ * GNU Affero General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU Affero General Public License\n+ * along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.\n+ */\n+\n+#include <tuple>\n+\n+#include \"indexes/CoveringCellIndex.h\"\n+\n+#include \"common/GeographyValue.hpp\"\n+#include \"common/NValue.hpp\"\n+#include \"common/tabletuple.h\"\n+#include \"storage/persistenttable.h\"\n+\n+namespace voltdb {\n+\n+    //    avg area of cells in level 0: 85,021,153.482 km^2.\n+    //    avg area of cells in level 1: 21,255,288.370 km^2.\n+    //    avg area of cells in level 2:  5,313,822.093 km^2.\n+    //    avg area of cells in level 3:  1,328,455.523 km^2.\n+    //    avg area of cells in level 4:    332,113.881 km^2.\n+    //    avg area of cells in level 5:     83,028.470 km^2.\n+    //    avg area of cells in level 6:     20,757.118 km^2.\n+    //    avg area of cells in level 7:      5,189.279 km^2.\n+    //    avg area of cells in level 8:      1,297.320 km^2.\n+    //    avg area of cells in level 9:        324.330 km^2.\n+    //    avg area of cells in level 10:        81.082 km^2.\n+    //    avg area of cells in level 11:        20.271 km^2.\n+    //    avg area of cells in level 12:         5.068 km^2.\n+    //    avg area of cells in level 13:         1.267 km^2.\n+    //    avg area of cells in level 14:         0.317 km^2.\n+    //    avg area of cells in level 15:         0.079 km^2.\n+    //    avg area of cells in level 16:         0.020 km^2.\n+    //    avg area of cells in level 17:         0.005 km^2.\n+    //    avg area of cells in level 18:         0.001 km^2.\n+    //    avg area of cells in level 19:         0.000 km^2.\n+\n+static const int MIN_CELL_LEVEL = 0;  // entire cube face\n+static const int MAX_CELL_LEVEL = 16; //\n+static const int CELL_LEVEL_MOD = 2;  // every other level\n+\n+static void getCovering(const Polygon &poly, std::vector<S2CellId> *coveringCells) {\n+    S2RegionCoverer coverer;\n+    coverer.set_min_level(MIN_CELL_LEVEL);\n+    coverer.set_max_level(MAX_CELL_LEVEL);\n+    coverer.set_max_cells(CoveringCellIndex::MAX_CELL_COUNT);\n+    coverer.set_level_mod(CELL_LEVEL_MOD);\n+    coverer.GetCovering(poly, coveringCells);\n+}\n+\n+\n+static CoveringCellIndex::CellKeyType setKeyFromCellId(uint64_t cellId, const TableTuple* tuple) {\n+    CoveringCellIndex::CellKeyType key;\n+    int keyOffset = 0;\n+    int intraKeyOffset = static_cast<int>(sizeof(uint64_t) - 1);\n+    key.insertKeyValue<uint64_t>(keyOffset, intraKeyOffset, cellId);\n+    if (tuple != NULL)\n+        key.setValue(tuple->address());\n+    return key;\n+}\n+\n+\n+static CoveringCellIndex::CellKeyType setKeyFromCellId(uint64_t cellId) {\n+    return setKeyFromCellId(cellId, NULL);\n+}\n+\n+\n+static CoveringCellIndex::TupleKeyType setKeyFromTuple(const TableTuple* tuple) {\n+    CoveringCellIndex::TupleKeyType key;\n+    int keyOffset = 0;\n+    int intraKeyOffset = static_cast<int>(sizeof(void*) - 1);\n+    key.insertKeyValue<uint64_t>(keyOffset, intraKeyOffset, reinterpret_cast<uint64_t>(tuple->address()));\n+    return key;\n+}\n+\n+\n+static uint64_t extractCellId(const CoveringCellIndex::CellKeyType &key) {\n+    int keyOffset = 0;\n+    int intraKeyOffset = static_cast<int>(sizeof(uint64_t) - 1);\n+    return key.extractKeyValue<uint64_t>(keyOffset, intraKeyOffset);\n+}\n+\n+\n+static void* extractTupleAddress(const CoveringCellIndex::TupleKeyType &key) {\n+    int keyOffset = 0;\n+    int intraKeyOffset = static_cast<int>(sizeof(void*) - 1);\n+    return reinterpret_cast<void*>(key.extractKeyValue<uint64_t>(keyOffset, intraKeyOffset));\n+}\n+\n+\n+static CoveringCellIndex::CellMapIterator& castToIter(IndexCursor& cursor) {\n+    return *reinterpret_cast<CoveringCellIndex::CellMapIterator*>(&(cursor.m_keyIter[0]));\n+}\n+\n+static CoveringCellIndex::CellMapIterator& castToEndIter(IndexCursor& cursor) {\n+    return *reinterpret_cast<CoveringCellIndex::CellMapIterator*>(&(cursor.m_keyEndIter[0]));\n+}\n+\n+\n+bool CoveringCellIndex::getPolygonFromTuple(const TableTuple *tuple, Polygon *poly) const {\n+    NValue nval = tuple->getNValue(m_columnIndex);\n+    if (! nval.isNull()) {\n+        const GeographyValue gv = ValuePeeker::peekGeographyValue(nval);\n+        poly->initFromGeography(gv);\n+        return true;\n+    }\n+\n+    return false;\n+}\n+\n+\n+void CoveringCellIndex::addEntryDo(const TableTuple *tuple,\n+                                   TableTuple *conflictTuple)\n+{\n+    Polygon poly;\n+    if (! getPolygonFromTuple(tuple, &poly)) {\n+        // Null polygons are not indexed.\n+        return;\n+    }\n+\n+    std::vector<S2CellId> covering;\n+    getCovering(poly, &covering);\n+\n+    BOOST_FOREACH(S2CellId &cell, covering) {\n+        m_cellEntries.insert(setKeyFromCellId(cell.id(), tuple), tuple->address());\n+    }\n+\n+    // Now update our tuple map for fast operations.\n+    TupleValueType cells;\n+    for (int i = 0; i < MAX_CELL_COUNT; ++i) {\n+        if (i < covering.size()) {\n+            cells[i] = covering[i].id();\n+        }\n+        else {\n+            cells[i] = S2CellId::Sentinel().id();\n+        }\n+    }\n+\n+    m_tupleEntries.insert(setKeyFromTuple(tuple), cells);\n+}\n+\n+bool CoveringCellIndex::moveToCoveringCell(const TableTuple* searchKey,\n+                                           IndexCursor &cursor) const\n+{\n+    cursor.m_forward = true;\n+\n+    GeographyPointValue pt = ValuePeeker::peekGeographyPointValue(searchKey->getNValue(0));\n+    if (pt.isNull()) {\n+        cursor.m_match.move(NULL);\n+        return false;\n+    }\n+\n+    S2CellId cell = S2CellId::FromPoint(pt.toS2Point());\n+\n+    // Start at the highest level (smallest cells) and work to larger cells.\n+    // Going the other way (largest to smallest cells) would require more state,\n+    // since a cell has just one parent, but 4 children.\n+    assert (MAX_CELL_LEVEL % CELL_LEVEL_MOD == MIN_CELL_LEVEL % CELL_LEVEL_MOD);\n+    for (int level = MAX_CELL_LEVEL; level >= MIN_CELL_LEVEL; level -= CELL_LEVEL_MOD) {\n+        cell = cell.parent(level);\n+\n+        CellMapRange iterPair = m_cellEntries.equalRange(setKeyFromCellId(cell.id()));\n+\n+        CellMapIterator &mapIter = castToIter(cursor);\n+        CellMapIterator &mapEndIter = castToEndIter(cursor);\n+\n+        mapIter = iterPair.first;\n+        mapEndIter = iterPair.second;\n+\n+        if (! mapIter.equals(mapEndIter)) {\n+            cursor.m_match.move(const_cast<void*>(mapIter.value()));\n+            return true;\n+        }\n+\n+        // If no match, we'll try the next level.\n+    }\n+\n+    // If we get here there were no matches in any level.\n+    cursor.m_match.move(NULL);\n+    return false;\n+}\n+\n+TableTuple CoveringCellIndex::nextValueAtKey(IndexCursor& cursor) const\n+{\n+    if (cursor.m_match.isNullTuple()) {\n+        return cursor.m_match;\n+    }\n+\n+    TableTuple retval = cursor.m_match;\n+\n+    CellMapIterator &mapIter = castToIter(cursor);\n+    CellMapIterator &mapEndIter = castToEndIter(cursor);\n+\n+    S2CellId cell = S2CellId(extractCellId(mapIter.key()));\n+\n+    mapIter.moveNext();\n+    if (mapIter.equals(mapEndIter)) {\n+        // No more matches at the current level, but check the lower levels\n+        // (that is, the cells that contain the one we just checked).\n+        int nextLevel = cell.level() - CELL_LEVEL_MOD;\n+\n+        while (nextLevel >= MIN_CELL_LEVEL) {\n+            cell = cell.parent(nextLevel);\n+            CellMapRange iterPair = m_cellEntries.equalRange(setKeyFromCellId(cell.id()));\n+\n+            mapIter = iterPair.first;\n+            mapEndIter = iterPair.second;\n+            if (! mapIter.equals(mapEndIter)) {\n+                // There was a match in a larger, containing cell.\n+                cursor.m_match.move(const_cast<void*>(mapIter.value()));\n+                return retval;\n+            }\n+\n+            nextLevel -= CELL_LEVEL_MOD;\n+        }\n+\n+        // No more matches.\n+        cursor.m_match.move(NULL);\n+        return retval;\n+    }\n+\n+    // There is another match at the current level\n+    cursor.m_match.move(const_cast<void*>(mapIter.value()));\n+    return retval;","path":"src/ee/indexes/CoveringCellIndex.cpp","position":236,"original_position":236,"commit_id":"482ad79fbae7ebed21dd4f50681e71bdc7a10fbd","original_commit_id":"482ad79fbae7ebed21dd4f50681e71bdc7a10fbd","user":{"login":"paulmartel","id":1512099,"avatar_url":"https://avatars.githubusercontent.com/u/1512099?v=3","gravatar_id":"","url":"https://api.github.com/users/paulmartel","html_url":"https://github.com/paulmartel","followers_url":"https://api.github.com/users/paulmartel/followers","following_url":"https://api.github.com/users/paulmartel/following{/other_user}","gists_url":"https://api.github.com/users/paulmartel/gists{/gist_id}","starred_url":"https://api.github.com/users/paulmartel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paulmartel/subscriptions","organizations_url":"https://api.github.com/users/paulmartel/orgs","repos_url":"https://api.github.com/users/paulmartel/repos","events_url":"https://api.github.com/users/paulmartel/events{/privacy}","received_events_url":"https://api.github.com/users/paulmartel/received_events","type":"User","site_admin":false},"body":"The above could be a little simpler:\r\n\r\n        S2CellId cell = S2CellId(extractCellId(mapIter.key()));\r\n        int nextLevel = cell.level();\r\n    \r\n        mapIter.moveNext();\r\n        while (mapIter.equals(mapEndIter)) {\r\n            // No more matches at the current level, but check the lower levels\r\n            // (that is, the cells that contain the one we just checked).\r\n            nextLevel -= CELL_LEVEL_MOD;\r\n    \r\n            if (nextLevel < MIN_CELL_LEVEL) {\r\n                // No more matches.\r\n                cursor.m_match.move(NULL);\r\n                return retval;\r\n            }\r\n            cell = cell.parent(nextLevel);\r\n            CellMapRange iterPair = m_cellEntries.equalRange(setKeyFromCellId(cell.id()));\r\n    \r\n            mapIter = iterPair.first;\r\n            mapEndIter = iterPair.second;\r\n        }\r\n    \r\n        // There is another match at the current level\r\n        cursor.m_match.move(const_cast<void*>(mapIter.value()));\r\n        return retval;\r\n\r\n","created_at":"2016-02-22T18:56:40Z","updated_at":"2016-02-22T18:56:40Z","html_url":"https://github.com/VoltDB/voltdb/pull/3303#discussion_r53673082","pull_request_url":"https://api.github.com/repos/VoltDB/voltdb/pulls/3303","_links":{"self":{"href":"https://api.github.com/repos/VoltDB/voltdb/pulls/comments/53673082"},"html":{"href":"https://github.com/VoltDB/voltdb/pull/3303#discussion_r53673082"},"pull_request":{"href":"https://api.github.com/repos/VoltDB/voltdb/pulls/3303"}}},"pull_request":{"url":"https://api.github.com/repos/VoltDB/voltdb/pulls/3303","id":59899555,"html_url":"https://github.com/VoltDB/voltdb/pull/3303","diff_url":"https://github.com/VoltDB/voltdb/pull/3303.diff","patch_url":"https://github.com/VoltDB/voltdb/pull/3303.patch","issue_url":"https://api.github.com/repos/VoltDB/voltdb/issues/3303","number":3303,"state":"open","locked":false,"title":"Add a geospatial index type to the EE","user":{"login":"wolffcm","id":7902964,"avatar_url":"https://avatars.githubusercontent.com/u/7902964?v=3","gravatar_id":"","url":"https://api.github.com/users/wolffcm","html_url":"https://github.com/wolffcm","followers_url":"https://api.github.com/users/wolffcm/followers","following_url":"https://api.github.com/users/wolffcm/following{/other_user}","gists_url":"https://api.github.com/users/wolffcm/gists{/gist_id}","starred_url":"https://api.github.com/users/wolffcm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wolffcm/subscriptions","organizations_url":"https://api.github.com/users/wolffcm/orgs","repos_url":"https://api.github.com/users/wolffcm/repos","events_url":"https://api.github.com/users/wolffcm/events{/privacy}","received_events_url":"https://api.github.com/users/wolffcm/received_events","type":"User","site_admin":false},"body":"This just adds the implementation of the index itself and an EE unit test.","created_at":"2016-02-19T03:19:39Z","updated_at":"2016-02-22T18:56:40Z","closed_at":null,"merged_at":null,"merge_commit_sha":"adb72e099ce5381655ff4cfd54b34cb14830ff96","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/VoltDB/voltdb/pulls/3303/commits","review_comments_url":"https://api.github.com/repos/VoltDB/voltdb/pulls/3303/comments","review_comment_url":"https://api.github.com/repos/VoltDB/voltdb/pulls/comments{/number}","comments_url":"https://api.github.com/repos/VoltDB/voltdb/issues/3303/comments","statuses_url":"https://api.github.com/repos/VoltDB/voltdb/statuses/482ad79fbae7ebed21dd4f50681e71bdc7a10fbd","head":{"label":"VoltDB:ENG-9298-naive-gs-indexes-squash","ref":"ENG-9298-naive-gs-indexes-squash","sha":"482ad79fbae7ebed21dd4f50681e71bdc7a10fbd","user":{"login":"VoltDB","id":703910,"avatar_url":"https://avatars.githubusercontent.com/u/703910?v=3","gravatar_id":"","url":"https://api.github.com/users/VoltDB","html_url":"https://github.com/VoltDB","followers_url":"https://api.github.com/users/VoltDB/followers","following_url":"https://api.github.com/users/VoltDB/following{/other_user}","gists_url":"https://api.github.com/users/VoltDB/gists{/gist_id}","starred_url":"https://api.github.com/users/VoltDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VoltDB/subscriptions","organizations_url":"https://api.github.com/users/VoltDB/orgs","repos_url":"https://api.github.com/users/VoltDB/repos","events_url":"https://api.github.com/users/VoltDB/events{/privacy}","received_events_url":"https://api.github.com/users/VoltDB/received_events","type":"Organization","site_admin":false},"repo":{"id":2445970,"name":"voltdb","full_name":"VoltDB/voltdb","owner":{"login":"VoltDB","id":703910,"avatar_url":"https://avatars.githubusercontent.com/u/703910?v=3","gravatar_id":"","url":"https://api.github.com/users/VoltDB","html_url":"https://github.com/VoltDB","followers_url":"https://api.github.com/users/VoltDB/followers","following_url":"https://api.github.com/users/VoltDB/following{/other_user}","gists_url":"https://api.github.com/users/VoltDB/gists{/gist_id}","starred_url":"https://api.github.com/users/VoltDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VoltDB/subscriptions","organizations_url":"https://api.github.com/users/VoltDB/orgs","repos_url":"https://api.github.com/users/VoltDB/repos","events_url":"https://api.github.com/users/VoltDB/events{/privacy}","received_events_url":"https://api.github.com/users/VoltDB/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/VoltDB/voltdb","description":"VoltDB","fork":false,"url":"https://api.github.com/repos/VoltDB/voltdb","forks_url":"https://api.github.com/repos/VoltDB/voltdb/forks","keys_url":"https://api.github.com/repos/VoltDB/voltdb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/VoltDB/voltdb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/VoltDB/voltdb/teams","hooks_url":"https://api.github.com/repos/VoltDB/voltdb/hooks","issue_events_url":"https://api.github.com/repos/VoltDB/voltdb/issues/events{/number}","events_url":"https://api.github.com/repos/VoltDB/voltdb/events","assignees_url":"https://api.github.com/repos/VoltDB/voltdb/assignees{/user}","branches_url":"https://api.github.com/repos/VoltDB/voltdb/branches{/branch}","tags_url":"https://api.github.com/repos/VoltDB/voltdb/tags","blobs_url":"https://api.github.com/repos/VoltDB/voltdb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/VoltDB/voltdb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/VoltDB/voltdb/git/refs{/sha}","trees_url":"https://api.github.com/repos/VoltDB/voltdb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/VoltDB/voltdb/statuses/{sha}","languages_url":"https://api.github.com/repos/VoltDB/voltdb/languages","stargazers_url":"https://api.github.com/repos/VoltDB/voltdb/stargazers","contributors_url":"https://api.github.com/repos/VoltDB/voltdb/contributors","subscribers_url":"https://api.github.com/repos/VoltDB/voltdb/subscribers","subscription_url":"https://api.github.com/repos/VoltDB/voltdb/subscription","commits_url":"https://api.github.com/repos/VoltDB/voltdb/commits{/sha}","git_commits_url":"https://api.github.com/repos/VoltDB/voltdb/git/commits{/sha}","comments_url":"https://api.github.com/repos/VoltDB/voltdb/comments{/number}","issue_comment_url":"https://api.github.com/repos/VoltDB/voltdb/issues/comments{/number}","contents_url":"https://api.github.com/repos/VoltDB/voltdb/contents/{+path}","compare_url":"https://api.github.com/repos/VoltDB/voltdb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/VoltDB/voltdb/merges","archive_url":"https://api.github.com/repos/VoltDB/voltdb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/VoltDB/voltdb/downloads","issues_url":"https://api.github.com/repos/VoltDB/voltdb/issues{/number}","pulls_url":"https://api.github.com/repos/VoltDB/voltdb/pulls{/number}","milestones_url":"https://api.github.com/repos/VoltDB/voltdb/milestones{/number}","notifications_url":"https://api.github.com/repos/VoltDB/voltdb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/VoltDB/voltdb/labels{/name}","releases_url":"https://api.github.com/repos/VoltDB/voltdb/releases{/id}","deployments_url":"https://api.github.com/repos/VoltDB/voltdb/deployments","created_at":"2011-09-23T18:46:12Z","updated_at":"2016-02-22T16:22:15Z","pushed_at":"2016-02-22T17:23:33Z","git_url":"git://github.com/VoltDB/voltdb.git","ssh_url":"git@github.com:VoltDB/voltdb.git","clone_url":"https://github.com/VoltDB/voltdb.git","svn_url":"https://github.com/VoltDB/voltdb","homepage":"http://community.voltdb.com/","size":539917,"stargazers_count":740,"watchers_count":740,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":218,"mirror_url":null,"open_issues_count":29,"forks":218,"open_issues":29,"watchers":740,"default_branch":"master"}},"base":{"label":"VoltDB:master","ref":"master","sha":"d8887dae1e325c8c28c25058f0a938a8e41057b2","user":{"login":"VoltDB","id":703910,"avatar_url":"https://avatars.githubusercontent.com/u/703910?v=3","gravatar_id":"","url":"https://api.github.com/users/VoltDB","html_url":"https://github.com/VoltDB","followers_url":"https://api.github.com/users/VoltDB/followers","following_url":"https://api.github.com/users/VoltDB/following{/other_user}","gists_url":"https://api.github.com/users/VoltDB/gists{/gist_id}","starred_url":"https://api.github.com/users/VoltDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VoltDB/subscriptions","organizations_url":"https://api.github.com/users/VoltDB/orgs","repos_url":"https://api.github.com/users/VoltDB/repos","events_url":"https://api.github.com/users/VoltDB/events{/privacy}","received_events_url":"https://api.github.com/users/VoltDB/received_events","type":"Organization","site_admin":false},"repo":{"id":2445970,"name":"voltdb","full_name":"VoltDB/voltdb","owner":{"login":"VoltDB","id":703910,"avatar_url":"https://avatars.githubusercontent.com/u/703910?v=3","gravatar_id":"","url":"https://api.github.com/users/VoltDB","html_url":"https://github.com/VoltDB","followers_url":"https://api.github.com/users/VoltDB/followers","following_url":"https://api.github.com/users/VoltDB/following{/other_user}","gists_url":"https://api.github.com/users/VoltDB/gists{/gist_id}","starred_url":"https://api.github.com/users/VoltDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VoltDB/subscriptions","organizations_url":"https://api.github.com/users/VoltDB/orgs","repos_url":"https://api.github.com/users/VoltDB/repos","events_url":"https://api.github.com/users/VoltDB/events{/privacy}","received_events_url":"https://api.github.com/users/VoltDB/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/VoltDB/voltdb","description":"VoltDB","fork":false,"url":"https://api.github.com/repos/VoltDB/voltdb","forks_url":"https://api.github.com/repos/VoltDB/voltdb/forks","keys_url":"https://api.github.com/repos/VoltDB/voltdb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/VoltDB/voltdb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/VoltDB/voltdb/teams","hooks_url":"https://api.github.com/repos/VoltDB/voltdb/hooks","issue_events_url":"https://api.github.com/repos/VoltDB/voltdb/issues/events{/number}","events_url":"https://api.github.com/repos/VoltDB/voltdb/events","assignees_url":"https://api.github.com/repos/VoltDB/voltdb/assignees{/user}","branches_url":"https://api.github.com/repos/VoltDB/voltdb/branches{/branch}","tags_url":"https://api.github.com/repos/VoltDB/voltdb/tags","blobs_url":"https://api.github.com/repos/VoltDB/voltdb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/VoltDB/voltdb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/VoltDB/voltdb/git/refs{/sha}","trees_url":"https://api.github.com/repos/VoltDB/voltdb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/VoltDB/voltdb/statuses/{sha}","languages_url":"https://api.github.com/repos/VoltDB/voltdb/languages","stargazers_url":"https://api.github.com/repos/VoltDB/voltdb/stargazers","contributors_url":"https://api.github.com/repos/VoltDB/voltdb/contributors","subscribers_url":"https://api.github.com/repos/VoltDB/voltdb/subscribers","subscription_url":"https://api.github.com/repos/VoltDB/voltdb/subscription","commits_url":"https://api.github.com/repos/VoltDB/voltdb/commits{/sha}","git_commits_url":"https://api.github.com/repos/VoltDB/voltdb/git/commits{/sha}","comments_url":"https://api.github.com/repos/VoltDB/voltdb/comments{/number}","issue_comment_url":"https://api.github.com/repos/VoltDB/voltdb/issues/comments{/number}","contents_url":"https://api.github.com/repos/VoltDB/voltdb/contents/{+path}","compare_url":"https://api.github.com/repos/VoltDB/voltdb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/VoltDB/voltdb/merges","archive_url":"https://api.github.com/repos/VoltDB/voltdb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/VoltDB/voltdb/downloads","issues_url":"https://api.github.com/repos/VoltDB/voltdb/issues{/number}","pulls_url":"https://api.github.com/repos/VoltDB/voltdb/pulls{/number}","milestones_url":"https://api.github.com/repos/VoltDB/voltdb/milestones{/number}","notifications_url":"https://api.github.com/repos/VoltDB/voltdb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/VoltDB/voltdb/labels{/name}","releases_url":"https://api.github.com/repos/VoltDB/voltdb/releases{/id}","deployments_url":"https://api.github.com/repos/VoltDB/voltdb/deployments","created_at":"2011-09-23T18:46:12Z","updated_at":"2016-02-22T16:22:15Z","pushed_at":"2016-02-22T17:23:33Z","git_url":"git://github.com/VoltDB/voltdb.git","ssh_url":"git@github.com:VoltDB/voltdb.git","clone_url":"https://github.com/VoltDB/voltdb.git","svn_url":"https://github.com/VoltDB/voltdb","homepage":"http://community.voltdb.com/","size":539917,"stargazers_count":740,"watchers_count":740,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":218,"mirror_url":null,"open_issues_count":29,"forks":218,"open_issues":29,"watchers":740,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/VoltDB/voltdb/pulls/3303"},"html":{"href":"https://github.com/VoltDB/voltdb/pull/3303"},"issue":{"href":"https://api.github.com/repos/VoltDB/voltdb/issues/3303"},"comments":{"href":"https://api.github.com/repos/VoltDB/voltdb/issues/3303/comments"},"review_comments":{"href":"https://api.github.com/repos/VoltDB/voltdb/pulls/3303/comments"},"review_comment":{"href":"https://api.github.com/repos/VoltDB/voltdb/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/VoltDB/voltdb/pulls/3303/commits"},"statuses":{"href":"https://api.github.com/repos/VoltDB/voltdb/statuses/482ad79fbae7ebed21dd4f50681e71bdc7a10fbd"}}}}