You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by ta...@apache.org on 2020/04/13 16:41:56 UTC

[impala] branch master updated (293dc2e -> e93405f)

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

tarmstrong pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git.


    from 293dc2e  IMPALA-9620: Ensure group-by and cnf exprs are analyzed
     new c52b1d8  IMPALA-9428 Add arm64 atomic ops
     new b770d2d  Put transactional tables into 'managed' directory
     new d6f57eb  IMPALA-9644: Set core file size 0 in docker entrypoint script
     new e93405f  IMPALA-9625: Convert the name of a TAccessEvent to lowercase

The 4 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:
 be/src/common/init.cc                              |   2 +
 be/src/gutil/atomicops-internals-arm64.h           | 474 +++++++++++++++++++++
 be/src/gutil/atomicops.h                           |   2 +
 be/src/gutil/cpu.cc                                |   3 +
 docker/daemon_entrypoint.sh                        |   3 +
 .../java/org/apache/impala/analysis/Analyzer.java  |  12 +-
 .../org/apache/impala/analysis/AnalyzeDDLTest.java |   4 +-
 .../org/apache/impala/analysis/AuditingTest.java   |  10 +
 testdata/bin/generate-schema-statements.py         |  35 +-
 .../functional/functional_schema_template.sql      |   6 +
 .../QueryTest/create-table-like-file-orc.test      |  23 +-
 11 files changed, 530 insertions(+), 44 deletions(-)
 create mode 100644 be/src/gutil/atomicops-internals-arm64.h


[impala] 04/04: IMPALA-9625: Convert the name of a TAccessEvent to lowercase

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

tarmstrong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git

commit e93405f7600c2cefcf522fdc64162a9ceaac3aa3
Author: Fang-Yu Rao <fa...@cloudera.com>
AuthorDate: Wed Apr 8 12:05:25 2020 -0700

    IMPALA-9625: Convert the name of a TAccessEvent to lowercase
    
    Impala's COMPUTE STATS statement results in two registrations of the
    ALTER event for the corresponding table identified by its
    fully-qualified table name and a Set is used to maintained the audits.
    The first registration is in Analyzer#registerAuthAndAuditEvent() and
    the second is in Analyzer#getTable().
    
    In registerAuthAndAuditEvent(), the corresponding full table name
    table.getFullName() is produced by a call to Analyzer#resolveTableRef().
    The resulting database and table names are both in lowercase.
    
    However, in getTable(), the fully-qualified table name is produced by a
    call to Analyzer#getFqTableName(). The resulting database and table
    names are in their originally unconverted form provided by the user from
    the Impala shell. Hence, there is no guarantee that the database and
    table names are both in lowercase.
    
    Therefore, if a user does not provide lowercase database and table
    names, the returned full table names from registerAuthAndAuditEvent()
    and getTable() would differ, resulting in duplicate ALTER events for the
    same table. This patch resolves the inconsistencies by converting the
    name of a TAccessEvent to lowercase in addAccessEvent(), which is called
    in getTable().
    
    Testing:
    - Revised a FE test to verified we do not have duplicate ALTER events for
      the COMPUTE STATS statement.
    - Verified that the patch passes the exhaustive tests in the DEBUG build
      except for a flaky E2E test of test_column_storage_attributes.
    
    Change-Id: If0d9ba58da891921fafbfe7c6db358b51965e178
    Reviewed-on: http://gerrit.cloudera.org:8080/15689
    Reviewed-by: Impala Public Jenkins <im...@cloudera.com>
    Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
 fe/src/main/java/org/apache/impala/analysis/Analyzer.java    | 12 ++++++++----
 .../test/java/org/apache/impala/analysis/AuditingTest.java   | 10 ++++++++++
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/fe/src/main/java/org/apache/impala/analysis/Analyzer.java b/fe/src/main/java/org/apache/impala/analysis/Analyzer.java
index 91de1bc..367edab 100644
--- a/fe/src/main/java/org/apache/impala/analysis/Analyzer.java
+++ b/fe/src/main/java/org/apache/impala/analysis/Analyzer.java
@@ -2756,6 +2756,10 @@ public class Analyzer {
    */
   public Set<TAccessEvent> getAccessEvents() { return globalState_.accessEvents; }
   public void addAccessEvent(TAccessEvent event) {
+    // We convert 'event.name' to lowercase to avoid duplicate access events since a
+    // statement could possibly result in two calls to addAccessEvent(), e.g.,
+    // COMPUTE STATS.
+    event.name = event.name.toLowerCase();
     globalState_.accessEvents.add(event);
   }
 
@@ -2859,8 +2863,8 @@ public class Analyzer {
       TCatalogObjectType objectType = TCatalogObjectType.TABLE;
       if (table instanceof FeView) objectType = TCatalogObjectType.VIEW;
       for (Privilege priv : privilege) {
-        globalState_.accessEvents.add(new TAccessEvent(
-            fqTableName.toString(), objectType, priv.toString()));
+        addAccessEvent(new TAccessEvent(fqTableName.toString(), objectType,
+            priv.toString()));
       }
     }
     return table;
@@ -2943,8 +2947,8 @@ public class Analyzer {
     });
     // Propagate the exception if needed.
     FeDb retDb = getDb(dbName, throwIfDoesNotExist);
-    globalState_.accessEvents.add(new TAccessEvent(
-        dbName, TCatalogObjectType.DATABASE, privilege.toString()));
+    addAccessEvent(new TAccessEvent(dbName, TCatalogObjectType.DATABASE,
+        privilege.toString()));
     return retDb;
   }
 
diff --git a/fe/src/test/java/org/apache/impala/analysis/AuditingTest.java b/fe/src/test/java/org/apache/impala/analysis/AuditingTest.java
index c4278ab..4310c50 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AuditingTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AuditingTest.java
@@ -300,6 +300,16 @@ public class AuditingTest extends FrontendTestBase {
             "functional_seq_snap.alltypes", TCatalogObjectType.TABLE, "ALTER"),
         new TAccessEvent(
             "functional_seq_snap.alltypes", TCatalogObjectType.TABLE, "SELECT")));
+
+    // COMPUTE STATS results in two registrations of the ALTER event. Check we do not have
+    // duplicate ALTER events when the fully-qualified table name is not in lowercase.
+    accessEvents = AnalyzeAccessEvents(
+        "COMPUTE STATS FUNCTIONAL_SEQ_SNAP.ALLTYPES");
+    Assert.assertEquals(accessEvents, Sets.newHashSet(
+        new TAccessEvent(
+            "functional_seq_snap.alltypes", TCatalogObjectType.TABLE, "ALTER"),
+        new TAccessEvent(
+            "functional_seq_snap.alltypes", TCatalogObjectType.TABLE, "SELECT")));
   }
 
   @Test


[impala] 02/04: Put transactional tables into 'managed' directory

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

tarmstrong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git

commit b770d2d378d642dcc1bdda733c99cc80ca239dc3
Author: Zoltan Borok-Nagy <bo...@cloudera.com>
AuthorDate: Fri Apr 10 12:22:58 2020 +0200

    Put transactional tables into 'managed' directory
    
    HIVE-22794 disallows ACID tables outside of the 'managed' warehouse
    directory. This change updates data loading to make it conform to
    the new rules.
    
    The following tests had to be modified to use the new paths:
    * AnalyzeDDLTest.TestCreateTableLikeFileOrc()
    * create-table-like-file-orc.test
    
    Change-Id: Id3b65f56bf7f225b1d29aa397f987fdd7eb7176c
    Reviewed-on: http://gerrit.cloudera.org:8080/15708
    Reviewed-by: Impala Public Jenkins <im...@cloudera.com>
    Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
 .../org/apache/impala/analysis/AnalyzeDDLTest.java |  4 +--
 testdata/bin/generate-schema-statements.py         | 35 +++++++++++-----------
 .../functional/functional_schema_template.sql      |  6 ++++
 .../QueryTest/create-table-like-file-orc.test      | 23 ++------------
 4 files changed, 28 insertions(+), 40 deletions(-)

diff --git a/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java b/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java
index 7b2709a..b5b65fe 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java
@@ -2036,10 +2036,10 @@ public class AnalyzeDDLTest extends FrontendTestBase {
 
     // Inferring primitive and complex types
     AnalyzesOk("create table if not exists newtbl_DNE like orc " +
-        "'/test-warehouse/alltypestiny_orc_def/year=2009/month=1/" +
+        "'/test-warehouse/managed/alltypestiny_orc_def/year=2009/month=1/" +
         "base_0000001/bucket_00000_0'");
     AnalyzesOk("create table if not exists newtbl_DNE like orc " +
-        "'/test-warehouse/complextypestbl_orc_def/base_0000001/bucket_00000_0'");
+        "'/test-warehouse/managed/complextypestbl_orc_def/base_0000001/bucket_00000_0'");
 
     // check invalid paths
     AnalysisError("create table if not exists functional.zipcode_incomes like ORC " +
diff --git a/testdata/bin/generate-schema-statements.py b/testdata/bin/generate-schema-statements.py
index 8113498..590445c 100755
--- a/testdata/bin/generate-schema-statements.py
+++ b/testdata/bin/generate-schema-statements.py
@@ -315,13 +315,6 @@ def build_table_template(file_format, columns, partition_columns, row_format,
     # Kudu's test tables are managed.
     external = ""
 
-  # ORC tables are full ACID by default.
-  if (HIVE_MAJOR_VERSION == 3 and
-      file_format == 'orc' and
-      'transactional' not in tblproperties):
-    external = ""
-    tblproperties['transactional'] = 'true'
-
   all_tblproperties = []
   for key, value in tblproperties.iteritems():
     all_tblproperties.append("'{0}' = '{1}'".format(key, value))
@@ -655,15 +648,6 @@ def generate_statements(output_name, test_vectors, sections,
       force_reload = options.force_reload or (partition_columns and not alter) or \
           file_format == 'kudu'
 
-      hdfs_location = '{0}.{1}{2}'.format(db_name, table_name, db_suffix)
-      # hdfs file names for functional datasets are stored
-      # directly under /test-warehouse
-      # TODO: We should not need to specify the hdfs file path in the schema file.
-      # This needs to be done programmatically.
-      if data_set == 'functional':
-        hdfs_location = hdfs_location.split('.')[-1]
-      data_path = os.path.join(options.hive_warehouse_dir, hdfs_location)
-
       # Empty tables (tables with no "LOAD" sections) are assumed to be used for insert
       # testing. Since Impala currently only supports inserting into TEXT, PARQUET and
       # HBASE we need to create these tables with a supported insert format.
@@ -677,6 +661,23 @@ def generate_statements(output_name, test_vectors, sections,
           create_file_format = 'text'
 
       tblproperties = parse_table_properties(create_file_format, table_properties)
+      # ORC tables are full ACID by default.
+      if (HIVE_MAJOR_VERSION == 3 and
+          create_file_format == 'orc' and
+          'transactional' not in tblproperties):
+        tblproperties['transactional'] = 'true'
+
+      hdfs_location = '{0}.{1}{2}'.format(db_name, table_name, db_suffix)
+      # hdfs file names for functional datasets are stored
+      # directly under /test-warehouse
+      # TODO: We should not need to specify the hdfs file path in the schema file.
+      # This needs to be done programmatically.
+      if data_set == 'functional':
+        hdfs_location = hdfs_location.split('.')[-1]
+      # Transactional tables need to be put under the 'managed' directory.
+      if is_transactional(tblproperties):
+        hdfs_location = os.path.join('managed', hdfs_location)
+      data_path = os.path.join(options.hive_warehouse_dir, hdfs_location)
 
       output = impala_create
       if create_hive or file_format == 'hbase':
@@ -684,8 +685,6 @@ def generate_statements(output_name, test_vectors, sections,
       elif codec == 'lzo':
         # Impala CREATE TABLE doesn't allow INPUTFORMAT.
         output = hive_output
-      elif is_transactional(tblproperties):
-        output = hive_output
 
       # TODO: Currently, Kudu does not support partitioned tables via Impala.
       # If a CREATE_KUDU section was provided, assume it handles the partition columns
diff --git a/testdata/datasets/functional/functional_schema_template.sql b/testdata/datasets/functional/functional_schema_template.sql
index 6cf0b4b..e3dc3da 100644
--- a/testdata/datasets/functional/functional_schema_template.sql
+++ b/testdata/datasets/functional/functional_schema_template.sql
@@ -332,6 +332,8 @@ LOCATION '{hdfs_location}';
 ALTER TABLE {table_name}_tmp ADD IF NOT EXISTS PARTITION (year=2009, month=1);
 ALTER TABLE {table_name}_tmp ADD IF NOT EXISTS PARTITION (year=2009, month=2);
 ALTER TABLE {table_name}_tmp ADD IF NOT EXISTS PARTITION (year=2009, month=3);
+---- TABLE_PROPERTIES
+transactional=false
 ---- DEPENDENT_LOAD
 USE {db_name}{db_suffix};
 -- Step 4: Stream the data from tmp text table to desired format tmp table
@@ -458,6 +460,8 @@ USE {db_name}{db_suffix};
 ALTER TABLE {table_name}_tmp ADD IF NOT EXISTS PARTITION (year=2009, month=1);
 ALTER TABLE {table_name}_tmp ADD IF NOT EXISTS PARTITION (year=2009, month=2);
 ALTER TABLE {table_name}_tmp ADD IF NOT EXISTS PARTITION (year=2009, month=3);
+---- TABLE_PROPERTIES
+transactional=false
 ---- DEPENDENT_LOAD
 USE {db_name}{db_suffix};
 -- Step 4: Stream the data from tmp text table to desired format tmp table
@@ -1526,6 +1530,8 @@ CREATE EXTERNAL TABLE IF NOT EXISTS {db_name}{db_suffix}.{table_name} (
 ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
 STORED AS {file_format}
 LOCATION '{hdfs_location}';
+---- TABLE_PROPERTIES
+transactional=false
 ---- DEPENDENT_LOAD
 INSERT OVERWRITE TABLE {db_name}{db_suffix}.{table_name} SELECT * FROM {db_name}.{table_name};
 ---- LOAD
diff --git a/testdata/workloads/functional-query/queries/QueryTest/create-table-like-file-orc.test b/testdata/workloads/functional-query/queries/QueryTest/create-table-like-file-orc.test
index 5bbd7c1..3d36299 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/create-table-like-file-orc.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/create-table-like-file-orc.test
@@ -23,7 +23,7 @@ STRING, STRING, STRING
 ====
 ---- QUERY
 create table $DATABASE.temp_chars_table like ORC
-'$FILESYSTEM_PREFIX/test-warehouse/chars_tiny_orc_def/base_0000001/bucket_00000_0'
+'$NAMENODE/$MANAGED_WAREHOUSE_DIR/chars_tiny_orc_def/base_0000001/bucket_00000_0'
 ---- RESULTS
 'Table has been created.'
 ====
@@ -115,9 +115,8 @@ STRING, STRING, STRING
 ====
 ---- QUERY
 create external table transactional_complextypes_clone like ORC
-'$FILESYSTEM_PREFIX/test-warehouse/complextypestbl_orc_def/base_0000001/bucket_00000_0'
-stored as orc
-location '$FILESYSTEM_PREFIX/test-warehouse/complextypestbl_orc_def/';
+'$NAMENODE/$MANAGED_WAREHOUSE_DIR/complextypestbl_orc_def/base_0000001/bucket_00000_0'
+stored as orc;
 ---- RESULTS
 'Table has been created.'
 ====
@@ -133,19 +132,3 @@ describe transactional_complextypes_clone
 ---- TYPES
 STRING, STRING, STRING
 ====
----- QUERY
-select originaltransaction, rowid, `row`.id from transactional_complextypes_clone;
----- LABELS
-originaltransaction, rowid, row.id
----- RESULTS
-1,0,8
-1,0,1
-1,1,2
-1,2,3
-1,3,4
-1,4,5
-1,5,6
-1,6,7
----- TYPES
-BIGINT, BIGINT, BIGINT
-====


[impala] 03/04: IMPALA-9644: Set core file size 0 in docker entrypoint script

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

tarmstrong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git

commit d6f57eb97d11f9c43c8fe09e4ce80f2e2f539ff1
Author: Abhishek Rawat <ar...@cloudera.com>
AuthorDate: Sun Apr 12 01:27:41 2020 -0700

    IMPALA-9644: Set core file size 0 in docker
    entrypoint script
    
    Sets the core file size 0 in the 'daemon_entrypoint.sh'.
    
    Testing (docker container):
    - cat /proc/{pid_impalad}/limits returns core file size 0.
    - forced core dump using 'kill -11' and got message
      'Failed to write core dump. Core dumps have been disabled.'
    
    Change-Id: Icec7cb64bf1226c5b2ca72d048e0aeb8b7dae86d
    Reviewed-on: http://gerrit.cloudera.org:8080/15717
    Reviewed-by: Tim Armstrong <ta...@cloudera.com>
    Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
 docker/daemon_entrypoint.sh | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/docker/daemon_entrypoint.sh b/docker/daemon_entrypoint.sh
index d413162..c9d749b 100755
--- a/docker/daemon_entrypoint.sh
+++ b/docker/daemon_entrypoint.sh
@@ -56,4 +56,7 @@ if ! whoami ; then
   cat /etc/passwd
 fi
 
+# Set ulimit core file size 0.
+ulimit -c 0
+
 exec "$@"


[impala] 01/04: IMPALA-9428 Add arm64 atomic ops

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

tarmstrong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git

commit c52b1d8a689584f5502822cecd54c363c768f71d
Author: zhaorenhai <zh...@hotmail.com>
AuthorDate: Wed Feb 26 10:53:58 2020 +0000

    IMPALA-9428 Add arm64 atomic ops
    
    Atomic ops are implemented by asm.
    Different arc have diffent implementation.
    Here add arm64 atomic ops implementation.
    The file atomicops-internals-arm64.h is originally from here:
    https://github.com/protocolbuffers/protobuf/blob/3.5.x/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h
    and the commit hash is ec021f5.
    And I changed some instructions to newer version base
     the original file, such as ldxr + memory barrier was
     changed to ldaxr which has memory barrier natively.
    And also added some funtions which impala use.
    
    Change-Id: I469e0169193ad6ad8acca2a800c8b3f043083ddd
---
 be/src/common/init.cc                    |   2 +
 be/src/gutil/atomicops-internals-arm64.h | 474 +++++++++++++++++++++++++++++++
 be/src/gutil/atomicops.h                 |   2 +
 be/src/gutil/cpu.cc                      |   3 +
 4 files changed, 481 insertions(+)

diff --git a/be/src/common/init.cc b/be/src/common/init.cc
index e8069ef..278a563 100644
--- a/be/src/common/init.cc
+++ b/be/src/common/init.cc
@@ -305,8 +305,10 @@ void impala::InitCommonRuntime(int argc, char** argv, bool init_jvm,
   // Breakpad needs flags and logging to initialize.
   ABORT_IF_ERROR(RegisterMinidump(argv[0]));
 #ifndef THREAD_SANITIZER
+#ifndef __aarch64__
   AtomicOps_x86CPUFeaturesInit();
 #endif
+#endif
   impala::InitThreading();
   impala::datetime_parse_util::SimpleDateFormatTokenizer::InitCtx();
   impala::SeedOpenSSLRNG();
diff --git a/be/src/gutil/atomicops-internals-arm64.h b/be/src/gutil/atomicops-internals-arm64.h
new file mode 100644
index 0000000..5111ecc
--- /dev/null
+++ b/be/src/gutil/atomicops-internals-arm64.h
@@ -0,0 +1,474 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 Google Inc.  All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GUTIL_ATOMICOPS_INTERNALS_ARM64_H_
+#define GUTIL_ATOMICOPS_INTERNALS_ARM64_H_
+
+typedef int32_t Atomic32;
+typedef int64_t Atomic64;
+
+namespace base {
+namespace subtle {
+
+typedef int32_t Atomic32;
+typedef int64_t Atomic64;
+
+inline void MemoryBarrier() {
+  __asm__ __volatile__ ("dmb ish" ::: "memory");  // NOLINT
+}
+// NoBarrier versions of the operation include "memory" in the clobber list.
+// This is not required for direct usage of the NoBarrier versions of the
+// operations. However this is required for correctness when they are used as
+// part of the Acquire or Release versions, to ensure that nothing from outside
+// the call is reordered between the operation and the memory barrier. This does
+// not change the code generated, so has no or minimal impact on the
+// NoBarrier operations.
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %w[prev], %[ptr]                 \n\t"  // Load the previous value.
+    "cmp %w[prev], %w[old_value]           \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    "1:                                    \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"IJr" (old_value),
+      [new_value]"r" (new_value)
+    : "cc", "memory"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline Atomic32 Barrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldaxr %w[prev], %[ptr]                 \n\t"  // Load the previous value.
+    "cmp %w[prev], %w[old_value]           \n\t"
+    "bne 1f                                \n\t"
+    "stlxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    "1:                                    \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"IJr" (old_value),
+      [new_value]"r" (new_value)
+    : "cc", "memory"
+  );  // NOLINT
+
+  return prev;
+}
+
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %w[result], %[ptr]               \n\t"  // Load the previous value.
+    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [new_value]"r" (new_value)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic32 Barrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldaxr %w[result], %[ptr]               \n\t"  // Load the previous value.
+    "stlxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [new_value]"r" (new_value)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+
+inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr,
+                                       Atomic32 new_value) {
+  Atomic32 old_val = NoBarrier_AtomicExchange(ptr, new_value);
+  MemoryBarrier();
+  return old_val;
+}
+
+inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr,
+                                       Atomic32 new_value) {
+  MemoryBarrier();
+  return NoBarrier_AtomicExchange(ptr, new_value);
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  Atomic32 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                       \n\t"
+    "ldxr %w[result], %[ptr]                  \n\t"  // Load the previous value.
+    "add %w[result], %w[result], %w[increment]\n\t"
+    "stxr %w[temp], %w[result], %[ptr]        \n\t"  // Try to store the result.
+    "cbnz %w[temp], 0b                        \n\t"  // Retry on failure.
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [increment]"IJr" (increment)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  Atomic32 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                       \n\t"
+    "ldaxr %w[result], %[ptr]                  \n\t"  // Load the previous value.
+    "add %w[result], %w[result], %w[increment]\n\t"
+    "stlxr %w[temp], %w[result], %[ptr]        \n\t"  // Try to store the result.
+    "cbnz %w[temp], 0b                        \n\t"  // Retry on failure.
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [increment]"IJr" (increment)
+    : "memory"
+  );
+  return result;
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  MemoryBarrier();
+  return prev;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  MemoryBarrier();
+  Atomic32 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  return prev;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  __asm__ __volatile__ (  // NOLINT
+    "stlr %w[value], %[ptr]  \n\t"
+    : [ptr]"=Q" (*ptr)
+    : [value]"r" (value)
+    : "memory"
+  );  // NOLINT
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value;
+
+  __asm__ __volatile__ (  // NOLINT
+    "ldar %w[value], %[ptr]  \n\t"
+    : [value]"=r" (value)
+    : [ptr]"Q" (*ptr)
+    : "memory"
+  );  // NOLINT
+
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+// 64-bit versions of the operations.
+// See the 32-bit versions for comments.
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  Atomic64 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %[prev], %[ptr]                  \n\t"
+    "cmp %[prev], %[old_value]             \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    "1:                                    \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"IJr" (old_value),
+      [new_value]"r" (new_value)
+    : "cc", "memory"
+  );  // NOLINT
+
+  return prev;
+}
+
+
+inline Atomic64 Barrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  Atomic64 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldaxr %[prev], %[ptr]                  \n\t"
+    "cmp %[prev], %[old_value]             \n\t"
+    "bne 1f                                \n\t"
+    "stlxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    "1:                                    \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"IJr" (old_value),
+      [new_value]"r" (new_value)
+    : "cc", "memory"
+  );  // NOLINT
+
+  return prev;
+}
+
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+  Atomic64 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %[result], %[ptr]                \n\t"
+    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [new_value]"r" (new_value)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic64 Barrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+  Atomic64 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldaxr %[result], %[ptr]                \n\t"
+    "stlxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [new_value]"r" (new_value)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+
+inline void PauseCPU() {
+  __asm__ __volatile__("yield" : : : "memory");
+}
+
+inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr,
+                                       Atomic64 new_value) {
+  Atomic64 old_val = NoBarrier_AtomicExchange(ptr, new_value);
+  MemoryBarrier();
+  return old_val;
+}
+
+inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr,
+                                       Atomic64 new_value) {
+  MemoryBarrier();
+  return NoBarrier_AtomicExchange(ptr, new_value);
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 increment) {
+  Atomic64 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                     \n\t"
+    "ldxr %[result], %[ptr]                 \n\t"
+    "add %[result], %[result], %[increment] \n\t"
+    "stxr %w[temp], %[result], %[ptr]       \n\t"
+    "cbnz %w[temp], 0b                      \n\t"
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [increment]"IJr" (increment)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+                                        Atomic64 increment) {
+  Atomic64 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                     \n\t"
+    "ldaxr %[result], %[ptr]                 \n\t"
+    "add %[result], %[result], %[increment] \n\t"
+    "stlxr %w[temp], %[result], %[ptr]       \n\t"
+    "cbnz %w[temp], 0b                      \n\t"
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [increment]"IJr" (increment)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  MemoryBarrier();
+
+  return prev;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  MemoryBarrier();
+  Atomic64 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+
+  return prev;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  __asm__ __volatile__ (  // NOLINT
+    "stlr %x[value], %[ptr]  \n\t"
+    : [ptr]"=Q" (*ptr)
+    : [value]"r" (value)
+    : "memory"
+  );  // NOLINT
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  Atomic64 value;
+
+  __asm__ __volatile__ (  // NOLINT
+    "ldar %x[value], %[ptr]  \n\t"
+    : [value]"=r" (value)
+    : [ptr]"Q" (*ptr)
+    : "memory"
+  );  // NOLINT
+
+  return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+}  // namespace subtle
+}  // namespace base
+
+#endif  // GUTIL_ATOMICOPS_INTERNALS_ARM64_GCC_H_
+
diff --git a/be/src/gutil/atomicops.h b/be/src/gutil/atomicops.h
index ad8d773..b358d6e 100644
--- a/be/src/gutil/atomicops.h
+++ b/be/src/gutil/atomicops.h
@@ -74,6 +74,8 @@
 #include "gutil/atomicops-internals-tsan.h"
 #elif defined(__APPLE__)
 #include "gutil/atomicops-internals-macosx.h"
+#elif defined(__GNUC__) && defined(__aarch64__)
+#include "gutil/atomicops-internals-arm64.h"
 #elif defined(__GNUC__) && defined(ARMV6)
 #include "gutil/atomicops-internals-arm-v6plus.h"
 #elif defined(ARMV3)
diff --git a/be/src/gutil/cpu.cc b/be/src/gutil/cpu.cc
index 3ebfa4a..d59a19c 100644
--- a/be/src/gutil/cpu.cc
+++ b/be/src/gutil/cpu.cc
@@ -269,6 +269,9 @@ void CPU::Initialize() {
 #elif defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
   cpu_brand_.assign(g_lazy_cpuinfo.Get().brand());
   has_broken_neon_ = g_lazy_cpuinfo.Get().has_broken_neon();
+#elif defined(__aarch64__)
+  cpu_brand_.assign("ARM64");
+  has_broken_neon_ = false;
 #else
   #error unknown architecture
 #endif