diff --git a/.github/release.yaml b/.github/release.yaml
new file mode 100644
index 0000000000..f550e52020
--- /dev/null
+++ b/.github/release.yaml
@@ -0,0 +1,18 @@
+changelog:
+ exclude:
+ labels:
+ - ignore-for-release
+ authors:
+ - dependabot
+ categories:
+ - title: Breaking Changes ðŸ›
+ labels:
+ - semver-major
+ - breaking-change
+ - title: New Features 🎉
+ labels:
+ - semver-minor
+ - enhancement
+ - title: Other Changes
+ labels:
+ - '*'
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index a110c018ec..1cd0c2526f 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -4,54 +4,93 @@ on:
workflow_dispatch:
pull_request:
push:
- branches: [main, contribute]
+ branches: ["*"]
tags: ["*"]
jobs:
build:
strategy:
matrix:
- runner: [windows-large]
- configuration: [ReleaseOS]
- addrsize: [64]
+ runner: [windows-large, macos-12-xl]
+ configuration: [Release, ReleaseOS]
+ python-version: ["3.11"]
include:
- - runner: windows-large
+ - runner: macos-12-xl
+ developer_dir: "/Applications/Xcode_14.0.1.app/Contents/Developer"
+ exclude:
+ - runner: macos-12-xl
configuration: ReleaseOS
- addrsize: 32
runs-on: ${{ matrix.runner }}
+ outputs:
+ viewer_channel: ${{ steps.build.outputs.viewer_channel }}
+ viewer_version: ${{ steps.build.outputs.viewer_version }}
+ imagename: ${{ steps.build.outputs.imagename }}
env:
+ AUTOBUILD_ADDRSIZE: 64
+ AUTOBUILD_BUILD_ID: ${{ github.run_id }}
AUTOBUILD_CONFIGURATION: ${{ matrix.configuration }}
- AUTOBUILD_ADDRSIZE: ${{ matrix.addrsize }}
+ # authorizes fetching private constituent packages
+ AUTOBUILD_GITHUB_TOKEN: ${{ secrets.SHARED_AUTOBUILD_GITHUB_TOKEN }}
AUTOBUILD_INSTALLABLE_CACHE: ${{ github.workspace }}/.autobuild-installables
AUTOBUILD_VARIABLES_FILE: ${{ github.workspace }}/.build-variables/variables
- AUTOBUILD_VSVER: "170" # vs2k22
- LOGFAIL: debug # Show details when tests fail
+ AUTOBUILD_VSVER: "170"
+ DEVELOPER_DIR: ${{ matrix.developer_dir }}
+ # Ensure that Linden viewer builds engage Bugsplat.
+ BUGSPLAT_DB: ${{ matrix.configuration != 'ReleaseOS' && 'SecondLife_Viewer_2018' || '' }}
+ BUGSPLAT_PASS: ${{ secrets.BUGSPLAT_PASS }}
+ BUGSPLAT_USER: ${{ secrets.BUGSPLAT_USER }}
+ build_coverity: false
+ build_log_dir: ${{ github.workspace }}/.logs
+ build_viewer: true
+ BUILDSCRIPTS_SHARED: ${{ github.workspace }}/.shared
+ # extracted and committed to viewer repo
+ BUILDSCRIPTS_SUPPORT_FUNCTIONS: ${{ github.workspace }}/buildscripts_support_functions
GIT_REF: ${{ github.head_ref || github.ref }}
+ LL_SKIP_REQUIRE_SYSROOT: 1
+ # Setting this variable directs Linden's TUT test driver code to capture
+ # test-program log output at the specified level, but to display it only if
+ # the individual test fails.
+ LOGFAIL: DEBUG
+ master_message_template_checkout: ${{ github.workspace }}/.master-message-template
+ # Only set variants to the one configuration: don't let build.sh loop
+ # over variants, let GitHub distribute variants over multiple hosts.
+ variants: ${{ matrix.configuration }}
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
+ - name: Setup python
+ uses: actions/setup-python@v4
+ with:
+ python-version: ${{ matrix.python-version }}
+
- name: Checkout build variables
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
repository: secondlife/build-variables
ref: viewer
path: .build-variables
+ - name: Checkout master-message-template
+ uses: actions/checkout@v4
+ with:
+ repository: secondlife/master-message-template
+ path: .master-message-template
+
- name: Install autobuild and python dependencies
- run: pip3 install autobuild llbase
+ run: pip3 install autobuild llsd
- name: Cache autobuild packages
uses: actions/cache@v3
id: cache-installables
with:
path: .autobuild-installables
- key: ${{ runner.os }}-${{ matrix.addrsize }}-${{ matrix.configuration }}-${{ hashFiles('autobuild.xml') }}
+ key: ${{ runner.os }}-64-${{ matrix.configuration }}-${{ hashFiles('autobuild.xml') }}
restore-keys: |
- ${{ runner.os }}-${{ matrix.addrsize }}-${{ matrix.configuration }}-
- ${{ runner.os }}-${{ matrix.addrsize }}-
+ ${{ runner.os }}-64-${{ matrix.configuration }}-
+ ${{ runner.os }}-64-
- name: Install windows dependencies
if: runner.os == 'Windows'
@@ -63,31 +102,266 @@ jobs:
env:
RUNNER_OS: ${{ runner.os }}
run: |
+ # set up things the viewer's build.sh script expects
+ set -x
+ mkdir -p "$build_log_dir"
+ mkdir -p "$BUILDSCRIPTS_SHARED/packages/lib/python"
+ source "$BUILDSCRIPTS_SUPPORT_FUNCTIONS"
+ if [[ "$OSTYPE" =~ cygwin|msys ]]
+ then
+ native_path() { cygpath --windows "$1"; }
+ shell_path() { cygpath --unix "$1"; }
+ else
+ native_path() { echo "$1"; }
+ shell_path() { echo "$1"; }
+ fi
+ finalize()
+ {
+ case "$1" in
+ true|0)
+ record_success "Build Succeeded"
+ ;;
+ *)
+ record_failure "Build Failed with $1"
+ ;;
+ esac
+ }
+ initialize_build()
+ {
+ echo "initialize_build"
+ }
+ initialize_version()
+ {
+ export revision="$AUTOBUILD_BUILD_ID"
+ }
+ python_cmd()
+ {
+ if [[ "x${1:0:1}" == "x-" ]] # -m, -c, etc.
+ then # if $1 is a switch, don't try to twiddle paths
+ "$(shell_path "$PYTHON_COMMAND")" "$@"
+ elif [[ "$(basename "$1")" == "codeticket.py" ]]
+ then # ignore any attempt to contact codeticket
+ echo "## $@"
+ else # running a script at an explicit path: fix path for Python
+ local script="$1"
+ shift
+ "$(shell_path "$PYTHON_COMMAND")" "$(native_path "$script")" "$@"
+ fi
+ }
+ repo_branch()
+ {
+ git -C "$1" branch | grep '^* ' | cut -c 3-
+ }
+ record_dependencies_graph()
+ {
+ echo "TODO: generate and post dependency graph"
+ }
+ # Since we're not uploading to codeticket, DO NOT sleep for minutes.
+ sleep()
+ {
+ echo "Not sleeping for $1 seconds"
+ }
+ export -f native_path shell_path finalize initialize_build initialize_version
+ export -f python_cmd repo_branch record_dependencies_graph sleep
+ ## Useful for diagnosing Windows LLProcess/LLLeap test failures
+ ##export APR_LOG="${RUNNER_TEMP}/apr.log"
+ export arch=$(uname | cut -b-6)
+ # Surprise! GH Windows runner's MINGW6 is a $arch value we've never
+ # seen before, so numerous tests don't know about it.
+ [[ "$arch" == "MINGW6" ]] && arch=CYGWIN
+ export AUTOBUILD="$(which autobuild)"
+ # Build with a tag like "Second_Life_Project_Shiny#abcdef0" to get a
+ # viewer channel "Second Life Project Shiny" (ignoring "#hash",
+ # needed to disambiguate tags).
+ if [[ "$GITHUB_REF_TYPE" == "tag" && "${GITHUB_REF_NAME:0:12}" == "Second_Life_" ]]
+ then viewer_channel="${GITHUB_REF_NAME%#*}"
+ export viewer_channel="${viewer_channel//_/ }"
+ else export viewer_channel="Second Life Test"
+ fi
+ echo "viewer_channel=$viewer_channel" >> "$GITHUB_OUTPUT"
+
# On windows we need to point the build to the correct python
# as neither CMake's FindPython nor our custom Python.cmake module
# will resolve the correct interpreter location.
if [[ "$RUNNER_OS" == "Windows" ]]; then
- export PYTHON="$(cygpath -m "$(which python)")"
+ export PYTHON="$(native_path "$(which python)")"
echo "Python location: $PYTHON"
+ export PYTHON_COMMAND="$PYTHON"
+ else
+ export PYTHON_COMMAND="python3"
fi
-
- autobuild configure -- -DVIEWER_CHANNEL="Second Life Test ${GIT_REF##*/}"
- autobuild build --no-configure
+ export PYTHON_COMMAND_NATIVE="$(native_path "$PYTHON_COMMAND")"
- # Find artifacts
- if [[ "$RUNNER_OS" == "Windows" ]]; then
- installer_path=$(find ./build-*/newview/ | grep '_Setup\.exe')
- installer_name="$(basename $installer_path)"
- elif [[ "$RUNNER_OS" == "macOS" ]]; then
- installer_path=$(find ./build-*/newview/ | grep '\.dmg')
- installer_name="$(basename $installer_path)"
+ ./build.sh
+
+ # Each artifact is downloaded as a distinct .zip file. Multiple jobs
+ # (per the matrix above) writing the same filepath to the same
+ # artifact name will *overwrite* that file. Moreover, they can
+ # interfere with each other, causing the upload to fail.
+ # https://github.com/actions/upload-artifact#uploading-to-the-same-artifact
+ # Given the size of our installers, and the fact that we typically
+ # only want to download just one instead of a single zip containing
+ # several, generate a distinct artifact name for each installer.
+ # If the matrix above can run multiple builds on the same
+ # platform, we must disambiguate on more than the platform name.
+ # e.g. if we were still running Windows 32-bit builds, we'd need to
+ # qualify the artifact with bit width.
+ if [[ "$AUTOBUILD_CONFIGURATION" == "ReleaseOS" ]]
+ then cfg_suffix='OS'
+ else cfg_suffix=''
fi
+ echo "artifact=$RUNNER_OS$cfg_suffix" >> $GITHUB_OUTPUT
- echo "installer_path=$installer_path" >> $GITHUB_OUTPUT
- echo "installer_name=$installer_name" >> $GITHUB_OUTPUT
-
- - name: Upload installer
+ - name: Upload executable
+ if: matrix.configuration != 'ReleaseOS' && steps.build.outputs.viewer_app
uses: actions/upload-artifact@v3
with:
- name: ${{ steps.build.outputs.installer_name }}
- path: ${{ steps.build.outputs.installer_path }}
+ name: "${{ steps.build.outputs.artifact }}-app"
+ path: |
+ ${{ steps.build.outputs.viewer_app }}
+
+ # The other upload of nontrivial size is the symbol file. Use a distinct
+ # artifact for that too.
+ - name: Upload symbol file
+ if: matrix.configuration != 'ReleaseOS'
+ uses: actions/upload-artifact@v3
+ with:
+ name: "${{ steps.build.outputs.artifact }}-symbols"
+ path: |
+ ${{ steps.build.outputs.symbolfile }}
+
+ - name: Upload metadata
+ if: matrix.configuration != 'ReleaseOS'
+ uses: actions/upload-artifact@v3
+ with:
+ name: "${{ steps.build.outputs.artifact }}-metadata"
+ # emitted by build.sh, possibly multiple lines
+ path: |
+ ${{ steps.build.outputs.metadata }}
+
+ - name: Upload physics package
+ uses: actions/upload-artifact@v3
+ # should only be set for viewer-private
+ if: matrix.configuration != 'ReleaseOS' && steps.build.outputs.physicstpv
+ with:
+ name: "${{ steps.build.outputs.artifact }}-physics"
+ # emitted by build.sh, zero or one lines
+ path: |
+ ${{ steps.build.outputs.physicstpv }}
+
+ sign-and-package-windows:
+ needs: build
+ runs-on: windows
+ steps:
+ - name: Sign and package Windows viewer
+ uses: secondlife/viewer-build-util/sign-pkg-windows@main
+ with:
+ vault_uri: "${{ secrets.AZURE_KEY_VAULT_URI }}"
+ cert_name: "${{ secrets.AZURE_CERT_NAME }}"
+ client_id: "${{ secrets.AZURE_CLIENT_ID }}"
+ client_secret: "${{ secrets.AZURE_CLIENT_SECRET }}"
+ tenant_id: "${{ secrets.AZURE_TENANT_ID }}"
+
+ sign-and-package-mac:
+ needs: build
+ runs-on: macos-latest
+ steps:
+ - name: Unpack Mac notarization credentials
+ id: note-creds
+ shell: bash
+ run: |
+ # In NOTARIZE_CREDS_MACOS we expect to find:
+ # USERNAME="..."
+ # PASSWORD="..."
+ # TEAM_ID="..."
+ eval "${{ secrets.NOTARIZE_CREDS_MACOS }}"
+ echo "::add-mask::$USERNAME"
+ echo "::add-mask::$PASSWORD"
+ echo "::add-mask::$TEAM_ID"
+ echo "note_user=$USERNAME" >> "$GITHUB_OUTPUT"
+ echo "note_pass=$PASSWORD" >> "$GITHUB_OUTPUT"
+ echo "note_team=$TEAM_ID" >> "$GITHUB_OUTPUT"
+ # If we didn't manage to retrieve all of these credentials, better
+ # find out sooner than later.
+ [[ -n "$USERNAME" && -n "$PASSWORD" && -n "$TEAM_ID" ]]
+
+ - name: Sign and package Mac viewer
+ uses: secondlife/viewer-build-util/sign-pkg-mac@main
+ with:
+ channel: ${{ needs.build.outputs.viewer_channel }}
+ imagename: ${{ needs.build.outputs.imagename }}
+ cert_base64: ${{ secrets.SIGNING_CERT_MACOS }}
+ cert_name: ${{ secrets.SIGNING_CERT_MACOS_IDENTITY }}
+ cert_pass: ${{ secrets.SIGNING_CERT_MACOS_PASSWORD }}
+ note_user: ${{ steps.note-creds.outputs.note_user }}
+ note_pass: ${{ steps.note-creds.outputs.note_pass }}
+ note_team: ${{ steps.note-creds.outputs.note_team }}
+
+ post-windows-symbols:
+ needs: build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Post Windows symbols
+ uses: secondlife/viewer-build-util/post-bugsplat-windows@main
+ with:
+ username: ${{ secrets.BUGSPLAT_USER }}
+ password: ${{ secrets.BUGSPLAT_PASS }}
+ database: "SecondLife_Viewer_2018"
+ channel: ${{ needs.build.outputs.viewer_channel }}
+ version: ${{ needs.build.outputs.viewer_version }}
+
+ post-mac-symbols:
+ needs: build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Post Mac symbols
+ uses: secondlife/viewer-build-util/post-bugsplat-mac@main
+ with:
+ username: ${{ secrets.BUGSPLAT_USER }}
+ password: ${{ secrets.BUGSPLAT_PASS }}
+ database: "SecondLife_Viewer_2018"
+ channel: ${{ needs.build.outputs.viewer_channel }}
+ version: ${{ needs.build.outputs.viewer_version }}
+
+ release:
+ needs: [sign-and-package-windows, sign-and-package-mac]
+ runs-on: ubuntu-latest
+ if: github.ref_type == 'tag' && startsWith(github.ref_name, 'Second_Life_')
+ steps:
+ - uses: actions/download-artifact@v3
+ with:
+ path: artifacts
+
+ - name: Reshuffle artifact files
+ uses: secondlife/viewer-build-util/release-artifacts@main
+ with:
+ input-path: artifacts
+ output-path: assets
+ # The *-app artifacts are for use only by the signing and
+ # packaging steps. Once we've generated signed installers, we no
+ # longer need them, and we CERTAINLY don't want to publish
+ # thousands of individual files as separate URLs.
+ exclude: |-
+ Windows-app
+ macOS-app
+ # Use just "Windows" or "macOS" prefix because these are the only
+ # artifacts in which we expect files from both platforms with
+ # colliding names (e.g. autobuild-package.xml). release-artifacts
+ # normally resolves collisions by prepending the artifact name, so
+ # when we anticipate collisions, it's good to keep the prefix
+ # short and sweet.
+ prefix: |-
+ Windows-metadata=Windows
+ macOS-metadata=macOS
+
+ # forked from softprops/action-gh-release
+ - uses: secondlife-3p/action-gh-release@v1
+ with:
+ # name the release page for the build number so we can find it
+ # easily (analogous to looking up a codeticket build page)
+ name: "v${{ github.run_id }}"
+ prerelease: true
+ generate_release_notes: true
+ # the only reason we generate a GH release is to post build products
+ fail_on_unmatched_files: true
+ files: "assets/*"
diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml
index 17c0ace02f..d626eef38d 100644
--- a/.github/workflows/pre-commit.yaml
+++ b/.github/workflows/pre-commit.yaml
@@ -11,7 +11,7 @@ jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: 3.x
diff --git a/.gitignore b/.gitignore
index 23a7f0cb4b..11266fdeaa 100755
--- a/.gitignore
+++ b/.gitignore
@@ -7,9 +7,18 @@
*.pyc
*.rej
*.swp
+*.vcxproj
+*.filters
+*.sln
+*.depend
+*.stamp
+*.rc
+
*~
# Specific paths and/or names
+CMakeCache.txt
+cmake_install.cmake
LICENSES
build-darwin-*
build-linux-*
@@ -17,6 +26,10 @@ debian/files
debian/secondlife-appearance-utility*
debian/secondlife-viewer*
indra/.distcc
+indra/cmake/*
+indra/out/*
+
+indra/packages/*
build-vc80/
build-vc100/
build-vc120/
@@ -75,4 +88,6 @@ tarfile_tmp
trivial_change_force_build
web/config.*
web/locale.*
-web/secondlife.com.*
\ No newline at end of file
+web/secondlife.com.*
+
+.env
diff --git a/autobuild.xml b/autobuild.xml
index bed4d58443..cf4d20c232 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1,20 +1,14 @@
+ boost
+
+ platforms
+
+ darwin64
+
+ archive
+
+ hash
+ 8539775e0a0783bd252bc548b20b3472a8254c31
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-boost/releases/download/v1.81-09d25a7/boost-1.81-darwin64-09d25a7.tar.zst
+
+ name
+ darwin64
windows64
archive
hash
- ec24f5945faa8f13807b83eeaeb994f8
+ d40c86fbcb6ce064d546165cbabbf035ea80e07b
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107592/938547/apr_suite-1.4.5.576669-windows64-576669.tar.bz2
+ https://github.com/secondlife/3p-boost/releases/download/v1.81-09d25a7/boost-1.81-windows64-09d25a7.tar.zst
name
windows64
- version
- 1.4.5.576669
-
- boost
-
- copyright
- (see individual source files)
- description
- Boost C++ Libraries
license
boost 1.0
license_file
LICENSES/boost.txt
+ copyright
+ (see individual source files)
+ version
+ 1.81-09d25a7
name
boost
+ description
+ Boost C++ Libraries
+
+ bugsplat
+
platforms
darwin64
@@ -118,65 +150,45 @@
archive
hash
- cae490999f05151e3a048b00d64237bb
+ d152f19f4a5a9c8013f006e19b1fcd88692bccf1
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109513/952781/boost-1.72-darwin64-577704.tar.bz2
+ https://github.com/secondlife/3p-bugsplat/releases/download/v1.0.7-527603a/bugsplat-1.0.7-527603a-darwin64-527603a.tar.zst
name
darwin64
- linux64
-
- archive
-
- hash
- 038853b97307a9b65de20c4c50098023
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/9675/45694/boost-1.65.1-linux64-509640.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- aa0f955996442b8d7097447de1f5a9fe
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109516/952793/boost-1.72-windows-577704.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- d3738a7ea84e2569017ae0237526da36
+ 1364da04333570b73c771e4f4acd1bacc7fc3f02
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109515/952797/boost-1.72-windows64-577704.tar.bz2
+ https://github.com/secondlife/3p-bugsplat/releases/download/v1.0.7-527603a/bugsplat-4.0.3.0-527603a-windows64-527603a.tar.zst
name
windows64
- version
- 1.72
-
- bugsplat
-
- copyright
- Copyright 2003-2017, BugSplat
- description
- Bugsplat crash reporting package
license
Proprietary
license_file
LICENSES/BUGSPLAT_LICENSE.txt
+ copyright
+ Copyright 2003-2017, BugSplat
+ version
+ 4.0.3.0-527603a
name
bugsplat
+ description
+ Bugsplat crash reporting package
+
+ colladadom
+
platforms
darwin64
@@ -184,103 +196,43 @@
archive
hash
- 02b569ac2bd71f201e3dd86ade7b3eeb
+ b1bb8a9c8d458d8842d79f9633fb61df12f1b0ad
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113876/983684/bugsplat-1.0.7.579696-darwin64-579696.tar.bz2
+ https://github.com/secondlife/3p-colladadom/releases/download/v2.3.ab0c124/colladadom-2.3.ab0c124-darwin64-ab0c124.tar.zst
name
darwin64
- windows
-
- archive
-
- hash
- 5b32c47ae8e8cf0d4106f08e8db18044
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113878/983697/bugsplat-4.0.3.0.579696-windows-579696.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- 79c005fd8a660f8551b3c9ede64fa4ef
+ 0df4c05d4efa3019afa4cbf09599df60b586fc5c
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113879/983696/bugsplat-4.0.3.0.579696-windows64-579696.tar.bz2
+ https://github.com/secondlife/3p-colladadom/releases/download/v2.3.ab0c124/colladadom-2.3.ab0c124-windows64-ab0c124.tar.zst
name
windows64
- version
- 4.0.3.0.579696
-
- colladadom
-
- copyright
- Copyright 2006 Sony Computer Entertainment Inc.
license
SCEA
license_file
LICENSES/collada.txt
+ copyright
+ Copyright 2006 Sony Computer Entertainment Inc.
+ version
+ 2.3.ab0c124
name
colladadom
- platforms
-
- darwin64
-
- archive
-
- hash
- cb76a5dcef6577fefff3f070029a4012
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/115496/994482/colladadom-2.3.580380-darwin64-580380.tar.bz2
-
- name
- darwin64
-
- windows
-
- archive
-
- hash
- 31996b4f4bbf478298edcd28a6581f92
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/115498/994495/colladadom-2.3.580380-windows-580380.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 9b0de47cd59e1aa88617d751c40dcff7
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/115497/994489/colladadom-2.3.580380-windows64-580380.tar.bz2
-
- name
- windows64
-
-
- version
- 2.3.580380
cubemaptoequirectangular
- copyright
- Copyright (c) 2017 Jaume Sanchez Elias, http://www.clicktorelease.com
- license
- MIT
- license_file
- LICENSES/CUBEMAPTOEQUIRECTANGULAR_LICENSE.txt
- name
- cubemaptoequirectangular
platforms
darwin64
@@ -288,9 +240,11 @@
archive
hash
- 7e4622b497bc465b01ff6d3e7e0b4214
+ d5fb3832a338bbe4891b823c64fdb4806706568e
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89303/815402/cubemaptoequirectangular-1.1.0-darwin64-564841.tar.bz2
+ https://github.com/secondlife/3p-cubemap_to_eqr_js/releases/download/v1.1.0-d7afe27/cubemaptoequirectangular-1.1.0-darwin64-d7afe27.tar.zst
name
darwin64
@@ -300,51 +254,41 @@
archive
hash
- ac54672e0b38f52726f5c99047c913e4
+ 77c53daf558f51aec6e9f4bd9e930a103630ee7d
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89306/815431/cubemaptoequirectangular-1.1.0-windows64-564841.tar.bz2
+ https://github.com/secondlife/3p-cubemap_to_eqr_js/releases/download/v1.1.0-d7afe27/cubemaptoequirectangular-1.1.0-linux64-d7afe27.tar.zst
- windows
-
- archive
-
- hash
- b5ea7097ae10037024b0c2b3df9812b5
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89307/815434/cubemaptoequirectangular-1.1.0-windows-564841.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- ac54672e0b38f52726f5c99047c913e4
+ 6c51855bcf3a8628289881fdaea08c25cf7b1b90
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89306/815431/cubemaptoequirectangular-1.1.0-windows64-564841.tar.bz2
+ https://github.com/secondlife/3p-cubemap_to_eqr_js/releases/download/v1.1.0-d7afe27/cubemaptoequirectangular-1.1.0-windows64-d7afe27.tar.zst
name
windows64
+ license
+ MIT
+ license_file
+ LICENSES/CUBEMAPTOEQUIRECTANGULAR_LICENSE.txt
+ copyright
+ Copyright (c) 2017 Jaume Sanchez Elias, http://www.clicktorelease.com
version
1.1.0
+ name
+ cubemaptoequirectangular
curl
- copyright
- Copyright (c) 1996 - 2014, Daniel Stenberg, (daniel@haxx.se).
- description
- Library for transferring data specified with URL syntax
- license
- curl
- license_file
- LICENSES/curl.txt
- name
- curl
platforms
darwin64
@@ -352,9 +296,11 @@
archive
hash
- 44d801e05811269d1bed7dbc75d85843
+ d4d5f27008de1ff7e86ae852841c68849b02eaea
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87786/805905/curl-7.54.1.563852-darwin64-563852.tar.bz2
+ https://github.com/secondlife/3p-curl/releases/download/v7.54.1-5a4a82d/curl-7.54.1-5a4a82d-darwin64-5a4a82d.tar.zst
name
darwin64
@@ -371,48 +317,36 @@
name
linux64
- windows
-
- archive
-
- hash
- 676f624d4ebdc2189caa43ef6dd8266d
- hash_algorithm
- md5
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87790/805917/curl-7.54.1.563852-windows-563852.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- b3db5a2cdf275c1af7758fbe2d14544a
+ 07423f41d1320ea405f493869f6460cf8c45def5
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87789/805918/curl-7.54.1.563852-windows64-563852.tar.bz2
+ https://github.com/secondlife/3p-curl/releases/download/v7.54.1-5a4a82d/curl-7.54.1-5a4a82d-windows64-5a4a82d.tar.zst
name
windows64
+ license
+ curl
+ license_file
+ LICENSES/curl.txt
+ copyright
+ Copyright (c) 1996 - 2014, Daniel Stenberg, (daniel@haxx.se).
version
- 7.54.1.563852
+ 7.54.1-5a4a82d
+ name
+ curl
+ description
+ Library for transferring data specified with URL syntax
dbus_glib
- copyright
- Copyright (C) Red Hat Inc.
- description
- D-Bus bindings for glib
- license
- Academic Free License v. 2.1
- license_file
- LICENSES/dbus-glib.txt
- name
- dbus_glib
platforms
linux64
@@ -428,21 +362,21 @@
linux64
+ license
+ Academic Free License v. 2.1
+ license_file
+ LICENSES/dbus-glib.txt
+ copyright
+ Copyright (C) Red Hat Inc.
version
0.76
+ name
+ dbus_glib
+ description
+ D-Bus bindings for glib
dictionaries
- copyright
- Copyright 2014 Apache OpenOffice software
- description
- Spell checking dictionaries to bundled into the viewer
- license
- various open source
- license_file
- LICENSES/dictionaries.txt
- name
- dictionaries
platforms
common
@@ -450,29 +384,31 @@
archive
hash
- d778c6a3475bc35ee8b9615dfc38b4a9
+ f6835c4d7745cd1cadfbce47b40331d08affb532
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55025/511964/dictionaries-1.538984-common-538984.tar.bz2
+ https://github.com/secondlife/3p-dictionaries/releases/download/v1.0.1-dev2.gf887629-f887629/dictionaries-common-None.tar.zst
name
common
+ license
+ various open source
+ license_file
+ LICENSES/dictionaries.txt
+ copyright
+ Copyright 2014 Apache OpenOffice software
version
- 1.538984
+ None
+ name
+ dictionaries
+ description
+ Spell checking dictionaries to bundled into the viewer
dullahan
- copyright
- Copyright (c) 2017, Linden Research, Inc.
- description
- A headless browser SDK that uses the Chromium Embedded Framework (CEF). It is designed to make it easier to write applications that render modern web content directly to a memory buffer, inject synthesized mouse and keyboard events as well as interact with web based features like JavaScript or cookies.
- license
- MPL
- license_file
- LICENSES/LICENSE.txt
- name
- dullahan
platforms
darwin64
@@ -480,40 +416,42 @@
archive
hash
- 439d92ec73f0500ba1671faad2bd8090
+ e4d568c166049ce61b39d69887b56d2382781a1a
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104637/916643/dullahan-1.12.4.202209142017_91.1.21_g9dd45fe_chromium-91.0.4472.114-darwin64-575005.tar.bz2
+ https://github.com/secondlife/dullahan/releases/download/v118.0.5993.54/dullahan-1.14.0.202310131309_118.4.1_g3dd6078_chromium-118.0.5993.54-darwin64-6b02a60.tar.zst
name
darwin64
- windows
-
- archive
-
- hash
- 2a7c01da15de77bc1fd1863327174d5e
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104638/916654/dullahan-1.12.4.202209142021_91.1.21_g9dd45fe_chromium-91.0.4472.114-windows-575005.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- d06bee9b2517fbb09ba1a65e6d675361
+ a00eae7f5dc430ae48389ab723ced39739b0a144
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104639/916659/dullahan-1.12.4.202209142021_91.1.21_g9dd45fe_chromium-91.0.4472.114-windows64-575005.tar.bz2
+ https://github.com/secondlife/dullahan/releases/download/v118.0.5993.54/dullahan-1.14.0.202310131404_118.4.1_g3dd6078_chromium-118.0.5993.54-windows64-6b02a60.tar.zst
name
windows64
+ license
+ MPL
+ license_file
+ LICENSES/LICENSE.txt
+ copyright
+ Copyright (c) 2017, Linden Research, Inc.
version
- 1.12.4.202209142021_91.1.21_g9dd45fe_chromium-91.0.4472.114
+ 1.14.0.202310131404_118.4.1_g3dd6078_chromium-118.0.5993.54
+ name
+ dullahan
+ description
+ A headless browser SDK that uses the Chromium Embedded Framework (CEF). It is designed to make it easier to write applications that render modern web content directly to a memory buffer, inject synthesized mouse and keyboard events as well as interact with web based features like JavaScript or cookies.
emoji_shortcodes
@@ -543,18 +481,6 @@
name
darwin64
- windows
-
- archive
-
- hash
- 3c5c4c7e3bb2eeef61e605b6690a63f3
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113244/980245/emoji_shortcodes-6.1.0.579438-windows-579438.tar.bz2
-
- name
- windows
-
windows64
archive
@@ -573,26 +499,80 @@
expat
- copyright
- Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd and Clark Cooper - Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
- description
- Expat is an XML parser library written in C
+ platforms
+
+ darwin64
+
+ archive
+
+ hash
+ b85526ca80b6a7e73c7870285cf68d568f742095
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-expat/releases/download/v2.1.1.1f36d02/expat-2.1.1.1f36d02-darwin64-1f36d02.tar.zst
+
+ name
+ darwin64
+
+ linux64
+
+ archive
+
+ hash
+ 4cd82e2dec06ddff19e9b3dc0254f2593ec80452
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-expat/releases/download/v2.1.1.1f36d02/expat-2.1.1.1f36d02-linux64-1f36d02.tar.zst
+
+ name
+ linux64
+
+ windows64
+
+ archive
+
+ hash
+ 47c01a89bc32c5740efe51be43e459ffd9b7cd34
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-expat/releases/download/v2.1.1.1f36d02/expat-2.1.1.1f36d02-windows64-1f36d02.tar.zst
+
+ name
+ windows64
+
+
license
expat
license_file
LICENSES/expat.txt
+ copyright
+ Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd and Clark Cooper - Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+ version
+ 2.1.1.1f36d02
name
expat
+ description
+ Expat is an XML parser library written in C
+
+ fmodstudio
+
platforms
darwin64
archive
+ creds
+ github
hash
- f4e80e0dfcab713a3da90cd8f7f23e7b
+ fb6797ff93b6e881b060d2a8b396d8d7477834ee
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76341/727265/expat-2.1.1.555519-darwin64-555519.tar.bz2
+ https://api.github.com/repos/secondlife/3p-fmodstudio/releases/assets/108908444
name
darwin64
@@ -601,120 +581,50 @@
archive
+ creds
+ github
hash
- 5e1f025d1cebd12db542080aa755257f
+ a378bd1604aa97ca763140911f9f4e463ced85c0
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/380/943/expat-2.1.1.500375-linux64-500375.tar.bz2
+ https://api.github.com/repos/secondlife/3p-fmodstudio/releases/assets/108908446
name
linux64
- windows
-
- archive
-
- hash
- cd4fe03473076c324d80ae3bd91a85bb
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76343/727273/expat-2.1.1.555519-windows-555519.tar.bz2
-
- name
- windows
-
windows64
archive
+ creds
+ github
hash
- d2d74d73b914150982b1883a3b96e60b
+ 72304491d86bd797b840999b255358f195b06609
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76344/727279/expat-2.1.1.555519-windows64-555519.tar.bz2
+ https://api.github.com/repos/secondlife/3p-fmodstudio/releases/assets/108908456
name
windows64
- version
- 2.1.1.555519
-
- fmodstudio
-
- copyright
- FMOD Studio by Firelight Technologies Pty Ltd.
- description
- FMOD Studio API
license
fmod
license_file
LICENSES/fmodstudio.txt
- name
- fmodstudio
- platforms
-
- darwin64
-
- archive
-
- hash
- 5a1d52ec3981292855a179be86988a02
- url
- https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/112152/972159/fmodstudio-2.02.13.578928-darwin64-578928.tar.bz2
-
- name
- darwin64
-
- linux64
-
- archive
-
- hash
- 24b86630ccdfb5b3221f90ca7a9704f6
- url
- https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/89682/818423/fmodstudio-2.02.03.565082-linux-565082.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 8594ec180b73be42d37b6f93ac59ab4a
- url
- https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/112153/972171/fmodstudio-2.02.13.578928-windows-578928.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 46941a2610f83c353e551d300e536c54
- url
- https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/112154/972170/fmodstudio-2.02.13.578928-windows64-578928.tar.bz2
-
- name
- windows64
-
-
+ copyright
+ FMOD Studio by Firelight Technologies Pty Ltd.
version
2.02.13.578928
+ name
+ fmodstudio
+ description
+ FMOD Studio API
fontconfig
- copyright
- Copyright (C) 2000,2001,2002,2003,2004,2006,2007 Keith Packard, 2005 Patrick Lam, 2009 Roozbeh Pournader, 2008,2009 Red Hat, Inc., 2008 Danilo Å egan, 2012 Google, Inc.
- description
- Fontconfig is a library for configuring and customizing font access.
- license
- bsd
- license_file
- LICENSES/fontconfig.txt
- name
- fontconfig
platforms
linux64
@@ -730,153 +640,81 @@
linux64
+ license
+ bsd
+ license_file
+ LICENSES/fontconfig.txt
+ copyright
+ Copyright (C) 2000,2001,2002,2003,2004,2006,2007 Keith Packard, 2005 Patrick Lam, 2009 Roozbeh Pournader, 2008,2009 Red Hat, Inc., 2008 Danilo Å egan, 2012 Google, Inc.
version
2.11.0
+ name
+ fontconfig
+ description
+ Fontconfig is a library for configuring and customizing font access.
freetype
- copyright
- Copyright 2006, 2007, 2008, 2009, 2010 by David Turner, Robert Wilhelm, and Werner Lemberg.
- description
- Font rendering library
+ platforms
+
+ darwin64
+
+ archive
+
+ hash
+ bc05f1d79b2935607af127c286b93a6804d27463
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-freetype/releases/download/v.2.12.1.1f4d9cc/freetype-2.12.1.1f4d9cc-darwin64-1f4d9cc.tar.zst
+
+ name
+ darwin64
+
+ linux64
+
+ archive
+
+ hash
+ 92b7a5f300c1cc419800e5a664216e5955b475fc
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-freetype/releases/download/v.2.12.1.1f4d9cc/freetype-2.12.1.1f4d9cc-linux64-1f4d9cc.tar.zst
+
+ name
+ linux64
+
+ windows64
+
+ archive
+
+ hash
+ 20fd901015919c1c70160dc49effa2624fcd591b
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-freetype/releases/download/v.2.12.1.1f4d9cc/freetype-2.12.1.1f4d9cc-windows64-1f4d9cc.tar.zst
+
+ name
+ windows64
+
+
license
FreeType
license_file
LICENSES/freetype.txt
+ copyright
+ Copyright 2006, 2007, 2008, 2009, 2010 by David Turner, Robert Wilhelm, and Werner Lemberg.
+ version
+ 2.12.1.1f4d9cc
name
freetype
- platforms
-
- darwin64
-
- archive
-
- hash
- 9cbcd452efa877fb8550c8c9b092b465
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/111566/967515/freetype-2.12.1.578664-darwin64-578664.tar.bz2
-
- name
- darwin64
-
- linux64
-
- archive
-
- hash
- 94cf61dfdbc86aae5bbaf0b5cb8a366c
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/874/1914/freetype-2.4.4.500865-linux64-500865.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- f3d7b72d10c162c9a8aa2ac4443ac52f
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/111571/967545/freetype-2.12.1.578664-windows-578664.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 96d3689043e939ae424060a8b498be1f
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/111570/967535/freetype-2.12.1.578664-windows64-578664.tar.bz2
-
- name
- windows64
-
-
- version
- 2.12.1.578664
+ description
+ Font rendering library
glext
- copyright
- Copyright (c) 2007-2010 The Khronos Group Inc.
- description
- glext headers define function prototypes and constants for OpenGL extensions
- license
- Copyright (c) 2007-2010 The Khronos Group Inc.
- license_file
- LICENSES/glext.txt
- name
- glext
- platforms
-
- darwin64
-
- archive
-
- hash
- 1bd3214ac23474ea4c869e386970a1be
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54835/510029/glext-68-darwin64-538965.tar.bz2
-
- name
- darwin64
-
- linux64
-
- archive
-
- hash
- 5f3c9d61b620f949b199ebd8885218ed
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-glext/rev/314200/arch/Linux/installer/glext-68-linux64-314200.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 6a311615bce59b01cf73ee65012a9b38
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54951/511711/glext-68-windows-538965.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- daf619dab1cf7518af6532b18800c4b0
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54924/511490/glext-68-windows64-538965.tar.bz2
-
- name
- windows64
-
-
- version
- 68
-
- glh_linear
-
- copyright
- Copyright (c) 2000 Cass Everitt
- description
- glh - is a platform-indepenedent C++ OpenGL helper library
- license
- BSD
- license_file
- LICENSES/glh-linear.txt
- name
- glh_linear
platforms
common
@@ -884,29 +722,63 @@
archive
hash
- dce3f3c01fddb400cb143c3283fe9259
+ 7cc58b3acb230a7e65ea5f0ff800be393eb4aa1b
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82754/775367/glh_linear-0.0.0-common-560278.tar.bz2
+ https://github.com/secondlife/3p-glext/releases/download/v69/glext-68-common-685b36e.tar.zst
name
common
- version
- 0.0.0
-
- googlemock
-
+ license
+ Copyright (c) 2007-2010 The Khronos Group Inc.
+ license_file
+ LICENSES/glext.txt
copyright
- Copyright 2008, Google Inc.
+ Copyright (c) 2007-2010 The Khronos Group Inc.
+ version
+ 68
+ name
+ glext
description
- a library for writing and using C++ mock classes
+ glext headers define function prototypes and constants for OpenGL extensions
+
+ glh_linear
+
+ platforms
+
+ common
+
+ archive
+
+ hash
+ 6604c1cca515d287e697997a8d5593d1cae172a9
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-glh_linear/releases/download/v1.0.1-dev2.g3253ed7-3253ed7/glh_linear-common-None.tar.zst
+
+ name
+ common
+
+
license
BSD
license_file
- LICENSES/gmock.txt
+ LICENSES/glh-linear.txt
+ copyright
+ Copyright (c) 2000 Cass Everitt
+ version
+ None
name
- googlemock
+ glh_linear
+ description
+ glh - is a platform-indepenedent C++ OpenGL helper library
+
+ googlemock
+
platforms
darwin64
@@ -914,63 +786,45 @@
archive
hash
- 772d3ae9d4a1d3e36eadcfb4b81ca47f
+ dce3174b12136746f5f910e311e895c1b47bf8fb
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109950/956085/googlemock-1.7.0.577943-darwin64-577943.tar.bz2
+ https://github.com/secondlife/3p-googlemock/releases/download/v1.7.0.2b109d4/googlemock-1.7.0.2b109d4-darwin64-2b109d4.tar.zst
name
darwin64
- linux64
-
- archive
-
- hash
- ff459b58695c76838782847a0b792104
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/9697/45717/googlemock-1.7.0.509686-linux64-509686.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 61df276991917f710d27cb578d9df25b
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109953/956105/googlemock-1.7.0.577943-windows-577943.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- cc1307e11133755eac29ab04ef240092
+ 265813f84b04c3b03f3d7d33e149b3d5e3cf31db
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109952/956106/googlemock-1.7.0.577943-windows64-577943.tar.bz2
+ https://github.com/secondlife/3p-googlemock/releases/download/v1.7.0.2b109d4/googlemock-1.7.0.2b109d4-windows64-2b109d4.tar.zst
name
windows64
+ license
+ BSD
+ license_file
+ LICENSES/gmock.txt
+ copyright
+ Copyright 2008, Google Inc.
version
- 1.7.0.577943
+ 1.7.0.2b109d4
+ name
+ googlemock
+ description
+ a library for writing and using C++ mock classes
gstreamer
- copyright
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- license
- LGPL
- license_file
- LICENSES/gstreamer.txt
- name
- gstreamer
platforms
linux64
@@ -986,19 +840,19 @@
linux64
+ license
+ LGPL
+ license_file
+ LICENSES/gstreamer.txt
+ copyright
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
version
0.10.6.314267
+ name
+ gstreamer
gtk-atk-pango-glib
- copyright
- Copyright (various, see sources)
- license
- lgpl
- license_file
- LICENSES/gtk-atk-pango-glib.txt
- name
- gtk-atk-pango-glib
platforms
linux64
@@ -1014,31 +868,33 @@
linux64
+ license
+ lgpl
+ license_file
+ LICENSES/gtk-atk-pango-glib.txt
+ copyright
+ Copyright (various, see sources)
version
0.1
+ name
+ gtk-atk-pango-glib
havok-source
- copyright
- Uses Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (and its Licensors). All Rights Reserved. See www.havok.com for details.
- description
- Havok source code for libs and demos
- license
- havok
- license_file
- LICENSES/havok.txt
- name
- havok-source
platforms
darwin64
archive
+ creds
+ github
hash
- ba229348c1d9d58519cd854ff9d8ef3d
+ a193ff65d6db48626d65d96c6124c6efca85e8ec
+ hash_algorithm
+ sha1
url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/55213/512968/havok_source-2012.1-2-darwin64-539117.tar.bz2
+ https://api.github.com/repos/secondlife/3p-havok-source/releases/assets/108912596
name
darwin64
@@ -1055,33 +911,35 @@
name
linux64
- windows
-
- archive
-
- hash
- 4ff2af85106907acb171bb1e38a3757e
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/55214/512993/havok_source-2012.1-2-windows-539117.tar.bz2
-
- name
- windows
-
windows64
archive
+ creds
+ github
hash
- bcaf4631ea10f7d09eecb73e8f5bef6c
+ ebfb82b6143874e7938b9d1e8a70d0a2e28aa818
+ hash_algorithm
+ sha1
url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/55212/512962/havok_source-2012.1-2-windows64-539117.tar.bz2
+ https://api.github.com/repos/secondlife/3p-havok-source/releases/assets/108912599
name
windows64
+ license
+ havok
+ license_file
+ LICENSES/havok.txt
+ copyright
+ Uses Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (and its Licensors). All Rights Reserved. See www.havok.com for details.
version
2012.1-2
+ name
+ havok-source
+ description
+ Havok source code for libs and demos
icu4c
@@ -1104,51 +962,91 @@
archive
hash
- acc2484ff03dfaf7652cac9f42ce198a
+ 47bc32b991385f1a6530e4c6179b07f64ca6edc7
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/112891/977803/icu4c-4.8.1-darwin64-579276.tar.bz2
+ https://github.com/secondlife/3p-icu4c/releases/download/v4.8.1-7d08d82/icu4c-4.8.1-darwin64-7d08d82.tar.zst
name
darwin64
- windows
-
- archive
-
- hash
- d88003ff2c3c9145bc2c7d2d2f80f9b1
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/112892/977809/icu4c-4.8.1-windows-579276.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- 2cdc400727294edcc144558d4f94fd00
+ b7db881dac80302e4d9010af34c0bf6ca9897df9
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/112893/977815/icu4c-4.8.1-windows64-579276.tar.bz2
+ https://github.com/secondlife/3p-icu4c/releases/download/v4.8.1-7d08d82/icu4c-4.8.1-windows64-7d08d82.tar.zst
name
windows64
version
- 4.8.1
+ 4.8.1-7d08d82
jpegencoderbasic
- copyright
- Andreas Ritter, www.bytestrom.eu, 11/2009
+ platforms
+
+ darwin64
+
+ archive
+
+ hash
+ f271809c0d4244128fb52a71226a4d7674e14e0a
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-jpeg_encoder_js/releases/download/v1.0-9165e47/jpegencoderbasic-1.0-darwin64-9165e47.tar.zst
+
+ name
+ darwin64
+
+ linux64
+
+ archive
+
+ hash
+ 35d6a617444fde9c8a5e998ef29dc43b95747637
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-jpeg_encoder_js/releases/download/v1.0-9165e47/jpegencoderbasic-1.0-linux64-9165e47.tar.zst
+
+
+ windows64
+
+ archive
+
+ hash
+ 8ec22e9fc8734ba3d1826f4b88171a6017cc8676
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-jpeg_encoder_js/releases/download/v1.0-9165e47/jpegencoderbasic-1.0-windows64-9165e47.tar.zst
+
+ name
+ windows64
+
+
license
NONE
license_file
LICENSES/JPEG_ENCODER_BASIC_LICENSE.txt
+ copyright
+ Andreas Ritter, www.bytestrom.eu, 11/2009
+ version
+ 1.0
name
jpegencoderbasic
+
+ jpeglib
+
platforms
darwin64
@@ -1156,9 +1054,11 @@
archive
hash
- c3c9e60bdc12b35e0e3d6b67d5635f60
+ 776d114aa1e3455bb13deaacd756deb07b53ecbe
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89304/815407/jpegencoderbasic-1.0-darwin64-564842.tar.bz2
+ https://github.com/secondlife/3p-jpeglib/releases/download/v8c.7846234/jpeglib-8c.7846234-darwin64-7846234.tar.zst
name
darwin64
@@ -1168,51 +1068,45 @@
archive
hash
- e70898903475d8ac2e81ff33278fc987
+ b4b2278bd2fcae85619e2145a243cca388d760d7
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89309/815433/jpegencoderbasic-1.0-windows64-564842.tar.bz2
-
-
- windows
-
- archive
-
- hash
- 0a376676dbb43fdd0c81ffdfbc5e6f81
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89308/815432/jpegencoderbasic-1.0-windows-564842.tar.bz2
+ https://github.com/secondlife/3p-jpeglib/releases/download/v8c.7846234/jpeglib-8c.7846234-linux64-7846234.tar.zst
name
- windows
+ linux64
windows64
archive
hash
- e70898903475d8ac2e81ff33278fc987
+ d50fcac69eeb9404638da07db96ee3e1191ecf93
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89309/815433/jpegencoderbasic-1.0-windows64-564842.tar.bz2
+ https://github.com/secondlife/3p-jpeglib/releases/download/v8c.7846234/jpeglib-8c.7846234-windows64-7846234.tar.zst
name
windows64
- version
- 1.0
-
- jpeglib
-
- copyright
- Copyright (C) 1991-2011, Thomas G. Lane, Guido Vollbeding.
- description
- JPEG encoding, decoding library
license
jpeglib
license_file
LICENSES/jpeglib.txt
+ copyright
+ Copyright (C) 1991-2011, Thomas G. Lane, Guido Vollbeding.
+ version
+ 8c.7846234
name
jpeglib
+ description
+ JPEG encoding, decoding library
+
+ jsoncpp
+
platforms
darwin64
@@ -1220,9 +1114,11 @@
archive
hash
- 3f2e34e3a2dac8eea957cad143a71dc5
+ 07761ab01e61d5d6b40d303ffafd85ec055ec9f7
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54847/510113/jpeglib-8c.538977-darwin64-538977.tar.bz2
+ https://github.com/secondlife/3p-jsoncpp/releases/download/v0.5.0.bc46e62/jsoncpp-0.5.0.bc46e62-darwin64-bc46e62.tar.zst
name
darwin64
@@ -1232,63 +1128,59 @@
archive
hash
- ba9c62863ec338a049de83c24639f57c
+ 97e268754808cb2fbd682c4d3beafd2c598e1ba7
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/3151/7568/jpeglib-8c.503140-linux64-503140.tar.bz2
+ https://github.com/secondlife/3p-jsoncpp/releases/download/v0.5.0.bc46e62/jsoncpp-0.5.0.bc46e62-linux64-bc46e62.tar.zst
name
linux64
- windows
-
- archive
-
- hash
- c8dee00ef13af40ec68becc25830e195
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54992/511854/jpeglib-8c.538977-windows-538977.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- 6f40620e86f3c9b91b6b5fe3c81776fc
+ 500e455b210d6bc4985185cef2472987ed3034bf
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54991/511847/jpeglib-8c.538977-windows64-538977.tar.bz2
+ https://github.com/secondlife/3p-jsoncpp/releases/download/v0.5.0.bc46e62/jsoncpp-0.5.0.bc46e62-windows64-bc46e62.tar.zst
name
windows64
- version
- 8c.538977
-
- jsoncpp
-
- copyright
- Copyright (c) 2007-2010 Baptiste Lepilleur
- description
- jsoncpp is an implementation of a JSON (http://json.org) reader and writer in C++.
license
public domain
license_file
LICENSES/jsoncpp.txt
+ copyright
+ Copyright (c) 2007-2010 Baptiste Lepilleur
+ version
+ 0.5.0.bc46e62
name
jsoncpp
+ description
+ jsoncpp is an implementation of a JSON (http://json.org) reader and writer in C++.
+
+ kdu
+
platforms
darwin64
archive
+ creds
+ github
hash
- 87d32aaac4183590c96edd0b6d9bf3e4
+ bcc7e2c34896fc9cbc41828dee8a4ddf54f10453
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54846/510106/jsoncpp-0.5.0.538976-darwin64-538976.tar.bz2
+ https://api.github.com/repos/secondlife/3p-kdu/releases/assets/108298968
name
darwin64
@@ -1297,54 +1189,50 @@
archive
+ creds
+ github
hash
- 9a658ae561c75e60bd9c0cee56731d21
+ 9de772df2ed12e9c742df6c90670c7cbbb9c93a6
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1475/3274/jsoncpp-0.5.0.501464-linux64-501464.tar.bz2
+ https://api.github.com/repos/secondlife/3p-kdu/releases/assets/108298969
name
linux64
- windows
-
- archive
-
- hash
- b73d9addab278eacc100bd312ab6ec5c
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54990/511840/jsoncpp-0.5.0.538976-windows-538976.tar.bz2
-
- name
- windows
-
windows64
archive
+ creds
+ github
hash
- 1b9ac5708cc526d2c5358ef0a427109d
+ 92533ff0f8c1881ad85e75800f9072c413ccf7b7
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54989/511833/jsoncpp-0.5.0.538976-windows64-538976.tar.bz2
+ https://api.github.com/repos/secondlife/3p-kdu/releases/assets/108298970
name
windows64
- version
- 0.5.0.538976
-
- kdu
-
- copyright
- Kakadu software
- description
- JPEG2000 library by Kakadu
license
Kakadu
license_file
LICENSES/kdu.txt
+ copyright
+ Kakadu software
+ version
+ 7.10.4.539108
name
kdu
+ description
+ JPEG2000 library by Kakadu
+
+ libhunspell
+
platforms
darwin64
@@ -1352,9 +1240,11 @@
archive
hash
- ccfd8eacd1ebe92715944094064ba2e4
+ d5757ab84d934fa358f299ab91e2e297beaa3dac
+ hash_algorithm
+ sha1
url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/55187/512570/kdu-7.10.4.539108-darwin64-539108.tar.bz2
+ https://github.com/secondlife/3p-libhunspell/releases/download/v1.3.2.650fb94/libhunspell-1.3.2.650fb94-darwin64-650fb94.tar.zst
name
darwin64
@@ -1364,53 +1254,45 @@
archive
hash
- a705a665810a71e7b0114a97ae9a2224
+ 6413d3bd4cd50c2a6b7f949eb4bd6f0c94feb984
+ hash_algorithm
+ sha1
url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/15256/98457/kdu-7.10.4.513518-linux64-513518.tar.bz2
+ https://github.com/secondlife/3p-libhunspell/releases/download/v1.3.2.650fb94/libhunspell-1.3.2.650fb94-linux64-650fb94.tar.zst
name
linux64
- windows
-
- archive
-
- hash
- 38574fbcb6c94c42745ef48748002e58
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/55189/512583/kdu-7.10.4.539108-windows-539108.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- 3dfeb869c781a766874f0aedc7d4fcef
+ c1be4a79b20435030b2e0e01b582c61b462c8376
+ hash_algorithm
+ sha1
url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/55188/512576/kdu-7.10.4.539108-windows64-539108.tar.bz2
+ https://github.com/secondlife/3p-libhunspell/releases/download/v1.3.2.650fb94/libhunspell-1.3.2.650fb94-windows64-650fb94.tar.zst
name
windows64
- version
- 7.10.4.539108
-
- libhunspell
-
- copyright
- See hunspell.txt
- description
- Spell checking library
license
LGPL
license_file
LICENSES/hunspell.txt
+ copyright
+ See hunspell.txt
+ version
+ 1.3.2.650fb94
name
libhunspell
+ description
+ Spell checking library
+
+ libndofdev
+
platforms
darwin64
@@ -1418,119 +1300,45 @@
archive
hash
- 2021ea3a19b81c82993e733709683303
+ e3dd320c90e67e0c80caf4d4df23257b0196dfb6
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76371/727419/libhunspell-1.3.2.555528-darwin64-555528.tar.bz2
+ https://github.com/secondlife/3p-libndofdev/releases/download/v0.1.8e9edc7/libndofdev-0.1.8e9edc7-darwin64-8e9edc7.tar.zst
name
darwin64
- linux64
-
- archive
-
- hash
- ffbdd109356d66ddfefd8a5d57f63f1f
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/533/1144/libhunspell-1.3.2.500526-linux64-500526.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 2253ec09136cc7c208481030d78d9dd7
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76369/727412/libhunspell-1.3.2.555528-windows-555528.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- 858d1708f6b3a74738a3d57a5387e20f
+ ae9d554e8839f42230b8ed6c850445d54654a38f
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76370/727413/libhunspell-1.3.2.555528-windows64-555528.tar.bz2
+ https://github.com/secondlife/3p-libndofdev/releases/download/v0.1.8e9edc7/libndofdev-0.1.8e9edc7-windows64-8e9edc7.tar.zst
name
windows64
- version
- 1.3.2.555528
-
- libndofdev
-
- copyright
- Copyright (c) 2007, 3Dconnexion, Inc. - All rights reserved.
- description
- 3DConnexion SDK
license
BSD
license_file
LICENSES/libndofdev.txt
+ copyright
+ Copyright (c) 2007, 3Dconnexion, Inc. - All rights reserved.
+ version
+ 0.1.8e9edc7
name
libndofdev
- platforms
-
- darwin64
-
- archive
-
- hash
- a487fff84208a45844602c4a1f68c974
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76356/727333/libndofdev-0.1.555523-darwin64-555523.tar.bz2
-
- name
- darwin64
-
- windows
-
- archive
-
- hash
- 4c839555bf0ed9ae60ffc3f8a7c96f9b
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76354/727340/libndofdev-0.1.555523-windows-555523.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- cbc033ae3b034b992b59f6de1034247c
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76355/727341/libndofdev-0.1.555523-windows64-555523.tar.bz2
-
- name
- windows64
-
-
- version
- 0.1.555523
+ description
+ 3DConnexion SDK
libpng
- copyright
- Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson
- description
- PNG Reference library
- license
- libpng
- license_file
- LICENSES/libpng.txt
- name
- libpng
platforms
darwin64
@@ -1538,9 +1346,11 @@
archive
hash
- 7a0059748d0b8733f2f9ce434cf604b8
+ fea8f0684a4ed0a73343651948b13049a135a92a
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107514/937867/libpng-1.6.38.576621-darwin64-576621.tar.bz2
+ https://github.com/secondlife/3p-libpng/releases/download/v1.6.38-ca06e99/libpng-1.6.38-ca06e99-darwin64-ca06e99.tar.zst
name
darwin64
@@ -1557,46 +1367,36 @@
name
linux64
- windows
-
- archive
-
- hash
- 3112013186ad60b0fc270a398d4dd499
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107513/937823/libpng-1.6.38.576621-windows-576621.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- 7c6bfcdb0d6162587cdbc436f595dd02
+ b91c116a1fda2377954355e56517634db0137699
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107512/937822/libpng-1.6.38.576621-windows64-576621.tar.bz2
+ https://github.com/secondlife/3p-libpng/releases/download/v1.6.38-ca06e99/libpng-1.6.38-ca06e99-windows64-ca06e99.tar.zst
name
windows64
+ license
+ libpng
+ license_file
+ LICENSES/libpng.txt
+ copyright
+ Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson
version
- 1.6.38.576621
+ 1.6.38-ca06e99
+ name
+ libpng
+ description
+ PNG Reference library
libuuid
- copyright
- Copyright (c) 2004-2008 The OSSP Project <http://www.ossp.org/>
- description
- OSSP uuid is a ISO-C:1999 application programming interface (API) and corresponding command line interface (CLI) for the generation of DCE 1.1, ISO/IEC 11578:1996 and RFC 4122 compliant Universally Unique Identifier (UUID).
- license
- UUID
- license_file
- LICENSES/uuid.txt
- name
- libuuid
platforms
linux64
@@ -1612,21 +1412,21 @@
linux64
+ license
+ UUID
+ license_file
+ LICENSES/uuid.txt
+ copyright
+ Copyright (c) 2004-2008 The OSSP Project <http://www.ossp.org/>
version
1.6.2
+ name
+ libuuid
+ description
+ OSSP uuid is a ISO-C:1999 application programming interface (API) and corresponding command line interface (CLI) for the generation of DCE 1.1, ISO/IEC 11578:1996 and RFC 4122 compliant Universally Unique Identifier (UUID).
libxml2
- copyright
- Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved.
- description
- Libxml2 is the XML C parser and toolkit developed for the Gnome project.
- license
- mit
- license_file
- LICENSES/libxml2.txt
- name
- libxml2
platforms
darwin64
@@ -1634,9 +1434,11 @@
archive
hash
- 6f37dd6c4a5174f358b6cc5d953f121b
+ 2c46547d9dc83c47f41eacc7e5092affa72f3eee
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87768/805766/libxml2-2.9.4.563845-darwin64-563845.tar.bz2
+ https://github.com/secondlife/3p-libxml2/releases/download/v2.9.4.7476681/libxml2-2.9.4.7476681-darwin64-7476681.tar.zst
name
darwin64
@@ -1646,53 +1448,45 @@
archive
hash
- 740fc93f195c77b3a0c0800b31878ecb
+ 4cda464277bfa6756ce4663a91cd724f3f45b8d8
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/890/1968/libxml2-2.9.4.500877-linux64-500877.tar.bz2
+ https://github.com/secondlife/3p-libxml2/releases/download/v2.9.4.7476681/libxml2-2.9.4.7476681-linux64-7476681.tar.zst
name
linux64
- windows
-
- archive
-
- hash
- fd85d3aa13fbdfd1f1ace587e95ef151
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87773/805797/libxml2-2.9.4.563845-windows-563845.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- d231d36c3b8942e0259aa2d9fcaa3b7e
+ 7e506d26f8cb6f205146e41d74095e7e27087e84
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87772/805795/libxml2-2.9.4.563845-windows64-563845.tar.bz2
+ https://github.com/secondlife/3p-libxml2/releases/download/v2.9.4.7476681/libxml2-2.9.4.7476681-windows64-7476681.tar.zst
name
windows64
+ license
+ mit
+ license_file
+ LICENSES/libxml2.txt
+ copyright
+ Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved.
version
- 2.9.4.563845
+ 2.9.4.7476681
+ name
+ libxml2
+ description
+ Libxml2 is the XML C parser and toolkit developed for the Gnome project.
llappearance_utility
- copyright
- Copyright (c) 2000-2012, Linden Research, Inc.
- description
- Linden Lab appearance utility for server-side avatar baking services.
- license
- Proprietary
- license_file
- LICENSES/llappearanceutility.txt
- name
- llappearance_utility
platforms
linux
@@ -1708,20 +1502,21 @@
linux
+ license
+ Proprietary
+ license_file
+ LICENSES/llappearanceutility.txt
+ copyright
+ Copyright (c) 2000-2012, Linden Research, Inc.
version
0.0.1
+ name
+ llappearance_utility
+ description
+ Linden Lab appearance utility for server-side avatar baking services.
llca
- copyright
- Copyright (c) 2016, Linden Research, Inc.; data provided by the Mozilla NSS Project.
-
- license
- mit
- license_file
- LICENSES/ca-license.txt
- name
- llca
platforms
common
@@ -1729,39 +1524,44 @@
archive
hash
- d6e7ab8483c348f223fd24028e27a52f
+ e50ea94bbaa4ff41bf53b84b7192df1a694c5337
hash_algorithm
- md5
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/93933/844890/llca-202202010217.567974-common-567974.tar.bz2
+ https://github.com/secondlife/llca/releases/download/v202310121525.0-d22bd98/llca-202310121530.0-common-d22bd98.tar.zst
name
common
+ license
+ mit
+ license_file
+ LICENSES/ca-license.txt
+ copyright
+ Copyright (c) 2016, Linden Research, Inc.; data provided by the Mozilla NSS Project.
+
version
- 202202010217.567974
+ 202310121530.0
+ name
+ llca
llphysicsextensions_source
- copyright
- Copyright (c) 2010, Linden Research, Inc.
- license
- internal
- license_file
- LICENSES/llphysicsextensions.txt
- name
- llphysicsextensions_source
platforms
darwin64
archive
+ creds
+ github
hash
- e51c6f5dfd76eb148348a44ff57e66c2
+ 48bca5d0233d1e724a59f649a2c6c7ac5f40ec3c
+ hash_algorithm
+ sha1
url
- https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/104810/918016/llphysicsextensions_source-1.0.575107-darwin64-575107.tar.bz2
+ https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/117009335
name
darwin64
@@ -1770,40 +1570,48 @@
archive
+ creds
+ github
hash
- c1b43e99c5ddccc18b0e9cb288bf75e1
+ 39f52d0350e130f41c5c758f7cb94e87b962c223
+ hash_algorithm
+ sha1
url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/4721/14828/llphysicsextensions_source-1.0.504710-linux64-504710.tar.bz2
+ https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/117009336
name
linux64
- windows
+ windows64
archive
+ creds
+ github
hash
- dbbe4cc568ac149d862e421cdda4dd48
+ 7b5e645fb7eb399abbea63bd21e8063bbb32a911
+ hash_algorithm
+ sha1
url
- https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/104809/918011/llphysicsextensions_source-1.0.575107-windows-575107.tar.bz2
+ https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/117009339
name
- windows
+ windows64
- version
- 1.0.565768
-
- llphysicsextensions_stub
-
- copyright
- Copyright (c) 2010, Linden Research, Inc.
license
internal
license_file
LICENSES/llphysicsextensions.txt
+ copyright
+ Copyright (c) 2010, Linden Research, Inc.
+ version
+ 1.0.565768
name
- llphysicsextensions_stub
+ llphysicsextensions_source
+
+ llphysicsextensions_stub
+
platforms
darwin64
@@ -1843,19 +1651,19 @@
windows
- version
- 1.0.542456
-
- llphysicsextensions_tpv
-
- copyright
- Copyright (c) 2010, Linden Research, Inc.
license
internal
license_file
- LICENSES/HavokSublicense.pdf
+ LICENSES/llphysicsextensions.txt
+ copyright
+ Copyright (c) 2010, Linden Research, Inc.
+ version
+ 1.0.542456
name
- llphysicsextensions_tpv
+ llphysicsextensions_stub
+
+ llphysicsextensions_tpv
+
platforms
darwin64
@@ -1882,18 +1690,6 @@
name
linux64
- windows
-
- archive
-
- hash
- 60e399f707bca32d0a4f7ee33ac4c35b
- url
- https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/84730/788138/llphysicsextensions_tpv-1.0.561752-windows-561752.tar.bz2
-
- name
- windows
-
windows64
archive
@@ -1907,17 +1703,19 @@
windows
+ license
+ internal
+ license_file
+ LICENSES/HavokSublicense.pdf
+ copyright
+ Copyright (c) 2010, Linden Research, Inc.
version
1.0.561752
+ name
+ llphysicsextensions_tpv
mesa
- license
- mesa
- license_file
- LICENSES/mesa.txt
- name
- mesa
platforms
linux
@@ -1933,23 +1731,77 @@
linux
+ license
+ mesa
+ license_file
+ LICENSES/mesa.txt
version
7.11.1.297294
+ name
+ mesa
meshoptimizer
- canonical_repo
- https://bitbucket.org/lindenlab/3p-meshoptimizer
- copyright
- Copyright (c) 2016-2021 Arseny Kapoulkine
- description
- Meshoptimizer. Mesh optimization library.
+ platforms
+
+ darwin64
+
+ archive
+
+ hash
+ 3bf88febd23656327a4ee2a3ebe99cae4b15573e
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-meshoptimizer/releases/download/v160-032f20a/meshoptimizer-160-darwin64-032f20a.tar.zst
+
+ name
+ darwin64
+
+ windows64
+
+ archive
+
+ hash
+ 13c0a33d9c49cc07b354527c7ef992d33f854c59
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-meshoptimizer/releases/download/v160-032f20a/meshoptimizer-160-windows64-032f20a.tar.zst
+
+ name
+ windows64
+
+
license
meshoptimizer
license_file
LICENSES/meshoptimizer.txt
+ copyright
+ Copyright (c) 2016-2021 Arseny Kapoulkine
+ version
+ 160
name
meshoptimizer
+ canonical_repo
+ https://bitbucket.org/lindenlab/3p-meshoptimizer
+ description
+ Meshoptimizer. Mesh optimization library.
+
+ mikktspace
+
+ canonical_repo
+ https://bitbucket.org/lindenlab/3p-mikktspace
+ copyright
+ Copyright (C) 2011 by Morten S. Mikkelsen
+ description
+ Mikktspace Tangent Generator
+ license
+ Copyright (C) 2011 by Morten S. Mikkelsen
+ license_file
+ mikktspace.txt
+ name
+ mikktspace
platforms
darwin64
@@ -1957,9 +1809,9 @@
archive
hash
- 30bc37db57bbd87c4b5f62634964242a
+ b48b7ac0792d3ea8f087d99d9e4a29d8
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/84218/784918/meshoptimizer-0.16.561408-darwin64-561408.tar.bz2
+ https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104415/914944/mikktspace-1-darwin64-574859.tar.bz2
name
darwin64
@@ -1969,9 +1821,9 @@
archive
hash
- ca3684bcf0447746cd2844e94f6d1fc7
+ 0a016b9c0c1e2c0b557e0124094da6c5
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/84219/784924/meshoptimizer-0.16.561408-windows-561408.tar.bz2
+ https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104407/914918/mikktspace-1-windows-574859.tar.bz2
name
windows
@@ -1981,72 +1833,78 @@
archive
hash
- aef28c089d20f69d13c9c3e113fb3895
+ 02e9e5b6fe6788f4d2babb83ec544843
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/84220/784931/meshoptimizer-0.16.561408-windows64-561408.tar.bz2
+ https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104406/914909/mikktspace-1-windows64-574859.tar.bz2
name
windows64
version
- 0.16.561408
+ 1
minizip-ng
- canonical_repo
- https://bitbucket.org/lindenlab/3p-minizip-ng
- copyright
- This project uses the zlib license. Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
- description
- minizip-ng is a zip manipulation library. Based on work of Gilles Vollant.
+ platforms
+
+ darwin64
+
+ archive
+
+ hash
+ 303fa93a0fd6c636a65fd9d5d53beceb84752b0e
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-minizip-ng/releases/download/v3.0.2.3e9876e/minizip_ng-3.0.2.3e9876e-darwin64-3e9876e.tar.zst
+
+ name
+ darwin64
+
+ linux64
+
+ archive
+
+ hash
+ d4f35ebcea53ab6e9f2e6cbc0d680b10d10b9c53
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-minizip-ng/releases/download/v3.0.2.3e9876e/minizip_ng-3.0.2.3e9876e-linux64-3e9876e.tar.zst
+
+ name
+ linux64
+
+ windows64
+
+ archive
+
+ hash
+ 5dc469172ba4c6015d5b771e516bc88a65d769eb
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-minizip-ng/releases/download/v3.0.2.3e9876e/minizip_ng-3.0.2.3e9876e-windows64-3e9876e.tar.zst
+
+ name
+ windows64
+
+
license
minizip-ng
license_file
LICENSES/minizip-ng.txt
+ copyright
+ This project uses the zlib license. Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
+ version
+ 3.0.2.3e9876e
name
minizip-ng
- platforms
-
- darwin64
-
- archive
-
- hash
- 843587a078102d86d90054d03354684d
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/95876/856095/minizip_ng-3.0.2.569217-darwin64-569217.tar.bz2
-
- name
- darwin64
-
- windows
-
- archive
-
- hash
- 26dc254f443ca9c5509547d7fbd9d8e5
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/95878/856107/minizip_ng-3.0.2.569217-windows-569217.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- e9241fa325f4014995b62193321e7a1c
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/95877/856106/minizip_ng-3.0.2.569217-windows64-569217.tar.bz2
-
- name
- windows64
-
-
- version
- 3.0.2.569217
+ canonical_repo
+ https://bitbucket.org/lindenlab/3p-minizip-ng
+ description
+ minizip-ng is a zip manipulation library. Based on work of Gilles Vollant.
nanosvg
@@ -2088,18 +1946,6 @@
name
linux
- windows
-
- archive
-
- hash
- 4e56202b09c026e08fc51116b22feabc
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/115456/994153/nanosvg-2022.09.27-windows-580364.tar.bz2
-
- name
- windows
-
windows64
archive
@@ -2118,17 +1964,6 @@
nghttp2
- copyright
- Copyright (c) 2012, 2014, 2015, 2016 Tatsuhiro Tsujikawa
-Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
- description
- Library providing HTTP 2 support for libcurl
- license
- MIT
- license_file
- LICENSES/nghttp2.txt
- name
- nghttp2
platforms
darwin64
@@ -2136,9 +1971,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- e4f784d8a035c51921a1562ca7a1bab6
+ fff611030a34e78b3a88168f64e4e33aef117bc3
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76357/727350/nghttp2-1.40.0.555524-darwin64-555524.tar.bz2
+ https://github.com/secondlife/3p-nghttp2/releases/download/v1.40.0.b1526c6/nghttp2-1.40.0.b1526c6-darwin64-b1526c6.tar.zst
name
darwin64
@@ -2148,97 +1985,80 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- c3c5ff7d2f7ac1143ef8d888192d4a53
+ 5798b5f6c8579ad44f211a873c072ee8d3fd8c93
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/9257/41579/nghttp2-1.25.0.509246-linux64-509246.tar.bz2
+ https://github.com/secondlife/3p-nghttp2/releases/download/v1.40.0.b1526c6/nghttp2-1.40.0.b1526c6-linux64-b1526c6.tar.zst
name
linux64
- windows
-
- archive
-
- hash
- af05aa2994c9845308fecd094b7b2d25
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76359/727360/nghttp2-1.40.0.555524-windows-555524.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- 5a55cede40eef16b9d1e47c418a2b77a
+ 05aad7759519719a54a6100fddd35b69e57f2386
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76358/727359/nghttp2-1.40.0.555524-windows64-555524.tar.bz2
+ https://github.com/secondlife/3p-nghttp2/releases/download/v1.40.0.b1526c6/nghttp2-1.40.0.b1526c6-windows64-b1526c6.tar.zst
name
windows64
+ license
+ MIT
+ license_file
+ LICENSES/nghttp2.txt
+ copyright
+ Copyright (c) 2012, 2014, 2015, 2016 Tatsuhiro Tsujikawa
+Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
+ version
+ 1.40.0.b1526c6
+ name
+ nghttp2
+ description
+ Library providing HTTP 2 support for libcurl
source_type
hg
- version
- 1.40.0.555524
nvapi
- copyright
- Copyright © 2012 NVIDIA Corporation. All rights reserved.
- description
- NVAPI provides an interface to NVIDIA devices.
+ platforms
+
+ windows64
+
+ archive
+
+ hash
+ 1ebe715fc1096198e343c41d50654c11509cdbba
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-nvapi/releases/download/v352.aac0e19/nvapi-352.aac0e19-windows64-aac0e19.tar.zst
+
+ name
+ windows64
+
+
license
NVIDIA Corporation Software License Agreement – NVAPI SDK
license_file
LICENSES/NVAPI_SDK_License_Agreement.pdf
+ copyright
+ Copyright © 2012 NVIDIA Corporation. All rights reserved.
+ version
+ 352.aac0e19
name
nvapi
- platforms
-
- windows
-
- archive
-
- hash
- 4305515ad326c911a390388366a9107b
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54947/511704/nvapi-352.539058-windows-539058.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 25c8ac919f24b8952653d38ec43640e5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54945/511697/nvapi-352.539058-windows64-539058.tar.bz2
-
- name
- windows64
-
-
- version
- 352.539058
+ description
+ NVAPI provides an interface to NVIDIA devices.
ogg_vorbis
- copyright
- Copyright (c) 2002, Xiph.org Foundation
- description
- Audio encoding library
- license
- ogg-vorbis
- license_file
- LICENSES/ogg-vorbis.txt
- name
- ogg_vorbis
platforms
darwin64
@@ -2246,9 +2066,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- a066f1d12caee1d87fc72f48169f9677
+ ad0dd0f608b868cc44c225ee48e114239fca2807
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54841/510071/ogg_vorbis-1.3.3-1.3.6.538971-darwin64-538971.tar.bz2
+ https://github.com/secondlife/3p-ogg_vorbis/releases/download/v1.3.3-1.3.6.e4101b6/ogg_vorbis-1.3.3-1.3.6.e4101b6-darwin64-e4101b6.tar.zst
name
darwin64
@@ -2265,61 +2087,51 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
name
linux64
- windows
-
- archive
-
- hash
- d4b8ed3fd679a2b484d2d1a66c063908
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54981/511789/ogg_vorbis-1.3.3-1.3.6.538971-windows-538971.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- ec4a657fe639bb458ee5132062146a7a
+ 2e73a0a5659c9a09eba2f94619aa5c23c7cc3937
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54980/511782/ogg_vorbis-1.3.3-1.3.6.538971-windows64-538971.tar.bz2
+ https://github.com/secondlife/3p-ogg_vorbis/releases/download/v1.3.3-1.3.6.e4101b6/ogg_vorbis-1.3.3-1.3.6.e4101b6-windows64-e4101b6.tar.zst
name
windows64
+ license
+ ogg-vorbis
+ license_file
+ LICENSES/ogg-vorbis.txt
+ copyright
+ Copyright (c) 2002, Xiph.org Foundation
version
- 1.3.3-1.3.6.538971
+ 1.3.3-1.3.6.e4101b6
+ name
+ ogg_vorbis
+ description
+ Audio encoding library
open-libndofdev
- copyright
- Copyright (c) 2008, Jan Ciger (jan.ciger (at) gmail.com)
- description
- Open Source replacement for 3DConnection SDK
license
BSD
license_file
LICENSES/libndofdev.txt
- name
- open-libndofdev
+ copyright
+ Copyright (c) 2008, Jan Ciger (jan.ciger (at) gmail.com)
version
0.3
+ name
+ open-libndofdev
+ description
+ Open Source replacement for 3DConnection SDK
openal
- copyright
- Creative Labs
- description
- OpenAL is a cross-platform 3D audio API appropriate for use with gaming applications and many other types of audio applications.
- license
- lgpl
- license_file
- LICENSES/openal.txt
- name
- openal
platforms
linux64
@@ -2327,55 +2139,119 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 7530fab3979312da75a903d87b73e3a9
+ e0fbc4874acc4167a6e2b6489fbb8258d98fd665
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openal/rev/314223/arch/Linux/installer/openal-1.12.854-1.1.0.314223-linux64-314223.tar.bz2
+ https://github.com/secondlife/3p-openal-soft/releases/download/v1.23.1-18e315c/openal-1.23.1-linux64-18e315c.tar.zst
name
linux64
- windows
-
- archive
-
- hash
- d9c86f79a6bb56a670e2801c33fd2dd1
- hash_algorithm
- md5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openal/rev/314223/arch/CYGWIN/installer/openal-1.12.854-1.1.0.314223-windows-314223.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- e0fdd9394a8cd8c6360b922f6f237e57
+ 6ae3b5310eb1988741bc55416681ca9d64f76f85
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openal/rev/314223/arch/CYGWIN/installer/openal-1.12.854-1.1.0.314223-windows64-314223.tar.bz2
+ https://github.com/secondlife/3p-openal-soft/releases/download/v1.23.1-18e315c/openal-1.23.1-windows64-18e315c.tar.zst
+
+ name
+ windows64
+
+ darwin64
+
+ archive
+
+ hash
+ 4edaef5f03a1122eae8467c4a04d9caccaaaf847
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-openal-soft/releases/download/v1.23.1-18e315c/openal-1.23.1-darwin64-18e315c.tar.zst
+
+ name
+ darwin64
+
+
+ license
+ LGPL2
+ license_file
+ LICENSES/openal-soft.txt
+ copyright
+ Copyright (C) 1999-2007 by authors.
+ version
+ 1.23.1
+ name
+ openal
+ description
+ OpenAL Soft is a software implementation of the OpenAL 3D audio API.
+
+ openjpeg
+
+ platforms
+
+ darwin64
+
+ archive
+
+ hash
+ c16deaf773cb2a5d001732122ee3ec74db1dceeb
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.0.ea12248/openjpeg-2.5.0.ea12248-darwin64-ea12248.tar.zst
+
+ name
+ darwin64
+
+ linux64
+
+ archive
+
+ hash
+ 8c277dde6076fb682cb07264dd70f6f2298b633f
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.0.ea12248/openjpeg-2.5.0.ea12248-linux64-ea12248.tar.zst
+
+ name
+ linux64
+
+ windows64
+
+ archive
+
+ hash
+ 2abf9535adf21ebdf2295f8a680300432abe6280
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.0.ea12248/openjpeg-2.5.0.ea12248-windows64-ea12248.tar.zst
name
windows64
- version
- 1.12.854-1.1.0.314223
-
- openjpeg
-
- copyright
- Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium; Copyright (c) 2002-2007, Professor Benoit Macq; Copyright (c) 2001-2003, David Janssens; Copyright (c) 2002-2003, Yannick Verschueren; Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe; Copyright (c) 2005, Herve Drolon, FreeImage Team; Copyright (c) 2006-2007, Parvatha Elangovan; Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr>; Copyright (c) 2010-2011, Kaori Hagihara; Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France; Copyright (c) 2012, CS Systemes d'Information, France;
- description
- The OpenJPEG library is an open-source JPEG 2000 codec written in C language.
license
BSD
license_file
LICENSES/openjpeg.txt
+ copyright
+ Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium; Copyright (c) 2002-2007, Professor Benoit Macq; Copyright (c) 2001-2003, David Janssens; Copyright (c) 2002-2003, Yannick Verschueren; Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe; Copyright (c) 2005, Herve Drolon, FreeImage Team; Copyright (c) 2006-2007, Parvatha Elangovan; Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr>; Copyright (c) 2010-2011, Kaori Hagihara; Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France; Copyright (c) 2012, CS Systemes d'Information, France;
+ version
+ 2.5.0.ea12248
name
openjpeg
+ description
+ The OpenJPEG library is an open-source JPEG 2000 codec written in C language.
+
+ openssl
+
platforms
darwin64
@@ -2383,9 +2259,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 8114c6a7e499ea20d325db0de08ce30a
+ b286e4a10cf6b1b2710b85ff96ffc0e41fd5fde8
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105469/923024/openjpeg-2.5.0.575496-darwin64-575496.tar.bz2
+ https://github.com/secondlife/3p-openssl/releases/download/v1.1.1q.de53f55/openssl-1.1.1q.de53f55-darwin64-de53f55.tar.zst
name
darwin64
@@ -2395,119 +2273,45 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- ac66f3197010b1549a5e4467aebbc27d
+ 5f6953db991ef6badb0525ecc98daf28d368e9e7
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1113/2571/openjpeg-1.5.1.501102-linux64-501102.tar.bz2
+ https://github.com/secondlife/3p-openssl/releases/download/v1.1.1q.de53f55/openssl-1.1.1q.de53f55-linux64-de53f55.tar.zst
name
linux64
- windows
-
- archive
-
- hash
- edc9388870d951632a6d595792293e05
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105472/923036/openjpeg-2.5.0.575496-windows-575496.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- b95f0732f2388ebb0ddf33d4a30e0ff1
+ 8bd3dea6d81de5e469b241a1b79e61efce6ecc05
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105471/923037/openjpeg-2.5.0.575496-windows64-575496.tar.bz2
+ https://github.com/secondlife/3p-openssl/releases/download/v1.1.1q.de53f55/openssl-1.1.1q.de53f55-windows64-de53f55.tar.zst
name
windows64
- version
- 2.5.0.575496
-
- openssl
-
- copyright
- Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved; Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- description
- Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) Library
license
openssl
license_file
LICENSES/openssl.txt
+ copyright
+ Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved; Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ version
+ 1.1.1q.de53f55
name
openssl
- platforms
-
- darwin64
-
- archive
-
- hash
- 142d0ad85d0ee4fbb673c9f9e414fbdd
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87769/805772/openssl-1.1.1l.563846-darwin64-563846.tar.bz2
-
- name
- darwin64
-
- linux64
-
- archive
-
- hash
- d50ccfbf0c1d249392919e2c46ad8d5c
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/8339/33495/openssl-1.0.2l.508328-linux64-508328.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 55bd833166d03f1467e2c7f24fa9143e
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87775/805841/openssl-1.1.1l.563846-windows-563846.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 6fefc60f68882fc6b246521b696497ab
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87774/805833/openssl-1.1.1l.563846-windows64-563846.tar.bz2
-
- name
- windows64
-
-
- version
- 1.1.1l.563846
+ description
+ Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) Library
pcre
- copyright
- Copyright (c) 1997-2014 University of Cambridge; Copyright(c) 2009-2014 Zoltan Herczeg; Copyright (c) 2007-2012, Google Inc.
- description
- PCRE Perl-compatible regular expression library
- license
- bsd
- license_file
- LICENSES/pcre-license.txt
- name
- pcre
platforms
darwin64
@@ -2515,9 +2319,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- d8c0f97fe5abef43e72b6f84aba698b2
+ b372d37596474043a62568e569b0ce155192f484
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54856/510176/pcre-8.35.538986-darwin64-538986.tar.bz2
+ https://github.com/secondlife/3p-pcre/releases/download/v8.35.979fd86/pcre-8.35.979fd86-darwin64-979fd86.tar.zst
name
darwin64
@@ -2534,56 +2340,50 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
name
linux64
- windows
-
- archive
-
- hash
- 3660db45793df3050b63920bfb7d8479
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55041/512002/pcre-8.35.538986-windows-538986.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- cdee8e8b48a66266550bf279c40abc22
+ 166564afb60a7536a038fae80e2fc9a41d6dbccb
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55038/511992/pcre-8.35.538986-windows64-538986.tar.bz2
+ https://github.com/secondlife/3p-pcre/releases/download/v8.35.979fd86/pcre-8.35.979fd86-windows64-979fd86.tar.zst
name
windows64
+ license
+ bsd
+ license_file
+ LICENSES/pcre-license.txt
+ copyright
+ Copyright (c) 1997-2014 University of Cambridge; Copyright(c) 2009-2014 Zoltan Herczeg; Copyright (c) 2007-2012, Google Inc.
version
- 8.35.538986
+ 8.35.979fd86
+ name
+ pcre
+ description
+ PCRE Perl-compatible regular expression library
slvoice
- copyright
- 2010 Vivox, including audio coding using Polycom¨ Siren14TM (ITU-T Rec. G.722.1 Annex C)
- description
- Vivox SDK components
- license
- Mixed
- license_file
- LICENSES/vivox_licenses.txt
- name
- slvoice
platforms
darwin64
archive
+ creds
+ github
hash
- b583668b28fde0490e6953f10e93e4ab
+ cc7c5bf53f83cff81d874ad66394df0991bd432c
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/98681/871545/slvoice-4.10.0000.32327.5fc3fe7c.571099-darwin64-571099.tar.bz2
+ https://api.github.com/repos/secondlife/3p-slvoice/releases/assets/108299352
name
darwin64
@@ -2600,44 +2400,38 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
name
linux64
- windows
-
- archive
-
- hash
- 6e0ed41653955afe8eeb8945776cf07b
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/98683/871560/slvoice-4.10.0000.32327.5fc3fe7c.571099-windows-571099.tar.bz2
-
- name
- windows
-
windows64
archive
+ creds
+ github
hash
- c39735851fd05c194d0be09b8f9e8cb7
+ 0c205371bb1731a9812b00556037729fdc057cbc
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/98682/871552/slvoice-4.10.0000.32327.5fc3fe7c.571099-windows64-571099.tar.bz2
+ https://api.github.com/repos/secondlife/3p-slvoice/releases/assets/108299356
name
windows64
+ license
+ Mixed
+ license_file
+ LICENSES/vivox_licenses.txt
+ copyright
+ 2010 Vivox, including audio coding using Polycom¨ Siren14TM (ITU-T Rec. G.722.1 Annex C)
version
4.10.0000.32327.5fc3fe7c.571099
+ name
+ slvoice
+ description
+ Vivox SDK components
threejs
- copyright
- Copyright © 2010-2021 three.js authors
- license
- MIT
- license_file
- LICENSES/THREEJS_LICENSE.txt
- name
- threejs
platforms
darwin64
@@ -2645,9 +2439,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 24440e8219e59d81423b68d3be381fef
+ cfed00d8ea7265c035c2d86a234b28efb0b23756
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89305/815412/threejs-0.132.2-darwin64-564843.tar.bz2
+ https://github.com/secondlife/3p-three_js/releases/download/v0.132.2-b8f6746/threejs-0.132.2-darwin64-b8f6746.tar.zst
name
darwin64
@@ -2657,115 +2453,53 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 46edf0f55417f8ef0d33a5c007bc3644
+ 9de1295b157c9913c28be81ff933c73493ecc132
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89310/815451/threejs-0.132.2-windows64-564843.tar.bz2
+ https://github.com/secondlife/3p-three_js/releases/download/v0.132.2-b8f6746/threejs-0.132.2-linux64-b8f6746.tar.zst
- windows
-
- archive
-
- hash
- e1303fb9f2242a79aee5fd9f97726ace
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89311/815452/threejs-0.132.2-windows-564843.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- 46edf0f55417f8ef0d33a5c007bc3644
+ 4141710fccbd1ea2b3b53d00e189bdfa2ee9d441
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89310/815451/threejs-0.132.2-windows64-564843.tar.bz2
+ https://github.com/secondlife/3p-three_js/releases/download/v0.132.2-b8f6746/threejs-0.132.2-windows64-b8f6746.tar.zst
name
windows64
+ license
+ MIT
+ license_file
+ LICENSES/THREEJS_LICENSE.txt
+ copyright
+ Copyright © 2010-2021 three.js authors
version
0.132.2
+ name
+ threejs
- tracy
+ tinygltf
canonical_repo
- https://bitbucket.org/lindenlab/3p-tracy
+ https://bitbucket.org/lindenlab/3p-tinygltf
copyright
- Copyright (c) 2017-2021, Bartosz Taudul (wolf@nereid.pl)
+ // Copyright (c) 2015 - Present Syoyo Fujita, Aurélien Chatelain and many contributors.
description
- Tracy Profiler Library
+ tinygltf import library
license
- bsd
+ MIT
license_file
- LICENSES/tracy_license.txt
+ LICENSES/tinygltf_license.txt
name
- tracy
- platforms
-
- darwin64
-
- archive
-
- hash
- da7317e4a81609f624f84780f28b07de
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/86972/801630/tracy-v0.7.8.563351-darwin64-563351.tar.bz2
-
- name
- darwin64
-
- windows
-
- archive
-
- hash
- 47c696cd2966c5cc3c8ba6115dd1f886
- hash_algorithm
- md5
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/86973/801641/tracy-v0.7.8.563351-windows-563351.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- b649ee6591e67d2341e886b3fc3484a7
- hash_algorithm
- md5
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/86974/801642/tracy-v0.7.8.563351-windows64-563351.tar.bz2
-
- name
- windows64
-
-
- source
- https://bitbucket.org/lindenlab/3p-tracy
- source_type
- git
- version
- v0.7.8.563351
-
- tut
-
- copyright
- Copyright 2002-2006 Vladimir Dyuzhev, Copyright 2007 Denis Kononenko, Copyright 2008-2009 Michał Rzechonek
- description
- TUT is a small and portable unit test framework for C++.
- license
- bsd
- license_file
- LICENSES/tut.txt
- name
- tut
+ tinygltf
platforms
common
@@ -2773,29 +2507,23 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 64e1c979aea2f74fe9c2d9d04573336d
+ 4dad1c0948141e1667c01a3ee755e4dc
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55001/511871/tut-2008.11.30-common-539059.tar.bz2
+ https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105849/926137/tinygltf-v2.5.0-common-575729.tar.bz2
name
common
+ source
+ https://bitbucket.org/lindenlab/3p-tinygltf
+ source_type
+ git
version
- 2008.11.30
+ v2.5.0
- uriparser
+ tracy
- copyright
- Copyright (C) 2007, Weijia Song <songweijia@gmail.com>, Sebastian Pipping <webmaster@hartwork.org>
- description
- uriparser is a strictly RFC 3986 compliant URI parsing and handling library written in C. uriparser is cross-platform, fast, supports Unicode and is licensed under the New BSD license.
- license
- New BSD license
- license_file
- LICENSES/uriparser.txt
- name
- uriparser
platforms
darwin64
@@ -2803,9 +2531,95 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- b97d0f6570104277de92d0d3f2d1111d
+ 9b6e1a1f4b0969d38a1ca8ee00aeb548
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89474/816487/uriparser-0.9.4-darwin64-564957.tar.bz2
+ https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/110584/960613/tracy-v0.8.1.578241-darwin64-578241.tar.bz2
+
+ name
+ darwin64
+
+ windows64
+
+ archive
+
+ hash
+ 05b72ae5d733aed7d3bf142287601cc6
+ hash_algorithm
+ md5
+ url
+ https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/110586/960637/tracy-v0.8.1.578241-windows64-578241.tar.bz2
+
+ name
+ windows64
+
+
+ license
+ bsd
+ license_file
+ LICENSES/tracy_license.txt
+ copyright
+ Copyright (c) 2017-2022, Bartosz Taudul (wolf@nereid.pl)
+ version
+ v0.8.1.235e98f
+ name
+ tracy
+ canonical_repo
+ https://bitbucket.org/lindenlab/3p-tracy
+ description
+ Tracy Profiler Library
+ source
+ https://bitbucket.org/lindenlab/3p-tracy
+ source_type
+ git
+ version
+ v0.8.1.578241
+
+ tut
+
+ platforms
+
+ common
+
+ archive
+
+ hash
+ 9f0bf4545f08df5381e0f39ccce3a57c6ec4b0f4
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-tut/releases/download/v2008.11.30-409bce5/tut-2008.11.30-common-409bce5.tar.zst
+
+ name
+ common
+
+
+ license
+ bsd
+ license_file
+ LICENSES/tut.txt
+ copyright
+ Copyright 2002-2006 Vladimir Dyuzhev, Copyright 2007 Denis Kononenko, Copyright 2008-2009 Michał Rzechonek
+ version
+ 2008.11.30
+ name
+ tut
+ description
+ TUT is a small and portable unit test framework for C++.
+
+ uriparser
+
+ platforms
+
+ darwin64
+
+ archive
+
+ hash
+ 4b6ee5113b1368ec9ff5b59e195adde370b9f585
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-uriparser/releases/download/v0.9.4-8fff38a/uriparser-0.9.4-darwin64-8fff38a.tar.zst
name
darwin64
@@ -2815,40 +2629,42 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 087375378f104cdac0cb0fe0ca43dd4d
+ 44dc74ec73e37c56bef6317d12a29d0435cb4bbb
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/346/880/uriparser-0.8.0.1-linux64-500342.tar.bz2
+ https://github.com/secondlife/3p-uriparser/releases/download/v0.9.4-8fff38a/uriparser-0.9.4-linux64-8fff38a.tar.zst
name
linux64
- windows
-
- archive
-
- hash
- e2600c798e220cc98c1cc77341aee00d
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89476/816496/uriparser-0.9.4-windows-564957.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- 50d857117d31844fc8b84b07b795fd00
+ e8b20edfc624f1d09bc83480932a9c844d47fc13
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89475/816497/uriparser-0.9.4-windows64-564957.tar.bz2
+ https://github.com/secondlife/3p-uriparser/releases/download/v0.9.4-8fff38a/uriparser-0.9.4-windows64-8fff38a.tar.zst
name
windows64
+ license
+ New BSD license
+ license_file
+ LICENSES/uriparser.txt
+ copyright
+ Copyright (C) 2007, Weijia Song <songweijia@gmail.com>, Sebastian Pipping <webmaster@hartwork.org>
version
0.9.4
+ name
+ uriparser
+ description
+ uriparser is a strictly RFC 3986 compliant URI parsing and handling library written in C. uriparser is cross-platform, fast, supports Unicode and is licensed under the New BSD license.
viewer-fonts
@@ -2876,18 +2692,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
name
darwin64
- windows
-
- archive
-
- hash
- 19c48abc168a1c4e0f0ec6d471b2e1bd
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113308/980632/viewer_fonts-1.579464-windows-579464.tar.bz2
-
- name
- windows
-
windows64
archive
@@ -2906,16 +2710,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
viewer-manager
- copyright
- Copyright (c) 2000-2012, Linden Research, Inc.
- description
- Linden Lab Viewer Management Process suite.
- license
- viewerlgpl
- license_file
- LICENSE
- name
- viewer-manager
platforms
darwin64
@@ -2923,107 +2717,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 8b091b1f13348eedadf66d7d81cb6bc1
+ d8bc8720846cfa31e23e7e1008e32ba6ad4a8322
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/116621/1003286/viewer_manager-3.0.580913-darwin64-580913.tar.bz2
-
- name
- darwin64
-
- windows
-
- archive
-
- hash
- 647e86470e02509b1cf89829d08dfd46
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/116623/1003293/viewer_manager-3.0.580913-windows-580913.tar.bz2
-
- name
- windows
-
-
- source
- https://bitbucket.org/lindenlab/vmp-standalone
- source_type
- hg
- version
- 3.0.580913
-
- vlc-bin
-
- copyright
- Copyright (C) 1998-2016 VLC authors and VideoLAN
- license
- GPL2
- license_file
- LICENSES/vlc.txt
- name
- vlc-bin
- platforms
-
- darwin64
-
- archive
-
- hash
- 738688816ebd76958e49772712a6b972
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/90004/820701/vlc_bin-3.0.16.565299-darwin64-565299.tar.bz2
-
- name
- darwin64
-
- windows
-
- archive
-
- hash
- 6801f91f3f27e626898bab90d40fc1c3
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/90005/820712/vlc_bin-3.0.16.565299-windows-565299.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 7f66982d6edf3c38f3493e28826d58e8
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/90006/820713/vlc_bin-3.0.16.565299-windows64-565299.tar.bz2
-
- name
- windows64
-
-
- version
- 3.0.16.565299
-
- xmlrpc-epi
-
- copyright
- Copyright: (C) 2000 Epinions, Inc.
- description
- XMLRPC Library
- license
- xmlrpc-epi
- license_file
- LICENSES/xmlrpc-epi.txt
- name
- xmlrpc-epi
- platforms
-
- darwin64
-
- archive
-
- hash
- 922a0dea32266897ed1911200438e1e1
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76372/727426/xmlrpc_epi-0.54.1.555529-darwin64-555529.tar.bz2
+ https://github.com/secondlife/viewer-manager/releases/download/v3.0.cc7ea1e/viewer_manager-3.0.cc7ea1e-darwin64-cc7ea1e.tar.zst
name
darwin64
@@ -3033,21 +2731,187 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 35df17c3eb673030dea4bde9191aa506
+ 228fae4ee0ce12b9d1d1b0a8ebb0bdf58ee521eb
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/727/1489/xmlrpc_epi-0.54.1.500719-linux64-500719.tar.bz2
+ https://github.com/secondlife/viewer-manager/releases/download/v3.0.cc7ea1e/viewer_manager-3.0.cc7ea1e-linux64-cc7ea1e.tar.zst
name
linux64
+ windows64
+
+ archive
+
+ hash
+ ca6999b64d96d45952fe872b381db9b2abc0248c
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/viewer-manager/releases/download/v3.0.cc7ea1e/viewer_manager-3.0.cc7ea1e-windows64-cc7ea1e.tar.zst
+
+ name
+ windows64
+
+
+ license
+ viewerlgpl
+ license_file
+ LICENSE
+ copyright
+ Copyright (c) 2000-2012, Linden Research, Inc.
+ version
+ 3.0.cc7ea1e
+ name
+ viewer-manager
+ description
+ Linden Lab Viewer Management Process suite.
+ source
+ https://bitbucket.org/lindenlab/vmp-standalone
+ source_type
+ hg
+
+ vlc-bin
+
+ platforms
+
+ darwin64
+
+ archive
+
+ hash
+ a26b47ab01a7e2c0add4c236886162c1135b3b79
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-vlc-bin/releases/download/v3.0.16.c219a5d/vlc_bin-3.0.16.c219a5d-darwin64-c219a5d.tar.zst
+
+ name
+ darwin64
+
+ windows64
+
+ archive
+
+ hash
+ d56002da7435bab166c88d59eeaf69fd87cd897d
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-vlc-bin/releases/download/v3.0.16.c219a5d/vlc_bin-3.0.16.c219a5d-windows64-c219a5d.tar.zst
+
+ name
+ windows64
+
+
+ license
+ GPL2
+ license_file
+ LICENSES/vlc.txt
+ copyright
+ Copyright (C) 1998-2016 VLC authors and VideoLAN
+ version
+ 3.0.16.c219a5d
+ name
+ vlc-bin
+
+ xmlrpc-epi
+
+ platforms
+
+ darwin64
+
+ archive
+
+ hash
+ aa12611374876196b3ebb6bda8d419a697217b8b
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-xmlrpc-epi/releases/download/v0.54.1.8a05acf/xmlrpc_epi-0.54.1.8a05acf-darwin64-8a05acf.tar.zst
+
+ name
+ darwin64
+
+ linux64
+
+ archive
+
+ hash
+ ad0c8b41ee4b4de216382bec46ee1c25962a3f12
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-xmlrpc-epi/releases/download/v0.54.1.8a05acf/xmlrpc_epi-0.54.1.8a05acf-linux64-8a05acf.tar.zst
+
+ name
+ linux64
+
+ windows64
+
+ archive
+
+ hash
+ e53fd38c14b8c47c7c84dead8a1b211bb8be170c
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-xmlrpc-epi/releases/download/v0.54.1.8a05acf/xmlrpc_epi-0.54.1.8a05acf-windows64-8a05acf.tar.zst
+
+ name
+ windows64
+
+
+ license
+ xmlrpc-epi
+ license_file
+ LICENSES/xmlrpc-epi.txt
+ copyright
+ Copyright: (C) 2000 Epinions, Inc.
+ version
+ 0.54.1.8a05acf
+ name
+ xmlrpc-epi
+ description
+ XMLRPC Library
+
+ vulkan_gltf
+
+ canonical_repo
+ https://bitbucket.org/lindenlab/3p-vulkan-gltf-pbr
+ copyright
+ Copyright (c) 2018 Sascha Willems
+ description
+ Vulkan GLTF Sample Implementation
+ license
+ Copyright (c) 2018 Sascha Willems
+ license_file
+ LICENSES/vulkan_gltf.txt
+ name
+ vulkan_gltf
+ platforms
+
+ darwin64
+
+ archive
+
+ hash
+ 8cff2060843db3db788511ee34a8e8cc
+ url
+ https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101316/891509/vulkan_gltf-1-darwin64-572743.tar.bz2
+
+ name
+ darwin64
+
windows
archive
hash
- 34b847e6b280048465fe7c6ce67fe05c
+ 58eea384be49ba756ce9c5e66669540b
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76374/727436/xmlrpc_epi-0.54.1.555529-windows-555529.tar.bz2
+ https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101318/891520/vulkan_gltf-1-windows-572743.tar.bz2
name
windows
@@ -3057,29 +2921,19 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 8fbe7c4ea22bb7f23a93c73884ebb34c
+ 79b6a11622c2f83cfc2b7cd1fafb867b
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76373/727435/xmlrpc_epi-0.54.1.555529-windows64-555529.tar.bz2
+ https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101319/891521/vulkan_gltf-1-windows64-572743.tar.bz2
name
windows64
version
- 0.54.1.555529
+ 1
xxhash
- copyright
- Copyright 2012-2020 Yann Collet
- description
- xxHash Extremely fast hash algorithm
- license
- bsd
- license_file
- LICENSES/xxhash.txt
- name
- xxhash
platforms
common
@@ -3094,34 +2948,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
name
common
-
- version
- 0.8.1
-
- zlib-ng
-
- canonical_repo
- https://bitbucket.org/lindenlab/3p-zlib-ng
- copyright
- Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
- description
- zlib data compression library for the next generation systems
- license
- zlib-ng
- license_file
- LICENSES/zlib-ng.txt
- name
- zlib-ng
- platforms
-
darwin64
archive
hash
- bf306e38bf81c6095e0967bdef6a2445
+ fdcc803a76a3359bb426db7dac161406676d51e7
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87759/805718/zlib_ng-2.0.5.563838-darwin64-563838.tar.bz2
+ https://github.com/secondlife/3p-xxhash/releases/download/v0.8.1.7501c90/xxhash-0.8.1.7501c90-darwin64-7501c90.tar.zst
name
darwin64
@@ -3131,56 +2967,108 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- dab6be8b0596c1e3354f2b6d41335131
+ 7acb3f94a549fbb9bd7bc16604e34f33c5365a9b
+ hash_algorithm
+ sha1
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/866/1898/zlib-1.2.8.500857-linux64-500857.tar.bz2
+ https://github.com/secondlife/3p-xxhash/releases/download/v0.8.1.7501c90/xxhash-0.8.1.7501c90-linux64-7501c90.tar.zst
name
linux64
- windows
-
- archive
-
- hash
- 8ffce5bd00e3d5afa8cb39b855237c4a
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87761/805730/zlib_ng-2.0.5.563838-windows-563838.tar.bz2
-
- name
- windows
-
windows64
archive
hash
- bd103a9129e57f7ea35886bc7750f8a6
+ 4522d075ea4703ef4b527c3039864ef735ea7953
+ hash_algorithm
+ sha1
url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87760/805729/zlib_ng-2.0.5.563838-windows64-563838.tar.bz2
+ https://github.com/secondlife/3p-xxhash/releases/download/v0.8.1.7501c90/xxhash-0.8.1.7501c90-windows64-7501c90.tar.zst
name
windows64
+ license
+ xxhash
+ license_file
+ LICENSES/xxhash.txt
+ copyright
+ Copyright (c) 2012-2021 Yann Collet
version
- 2.0.5.563838
+ 0.8.1.7501c90
+ name
+ xxhash
+ description
+ xxHash Library
+
+ zlib-ng
+
+ platforms
+
+ darwin64
+
+ archive
+
+ hash
+ dacc5f3fb307c4d1292ed1ffb1d595d83599062d
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-zlib-ng/releases/download/v1.2.11.zlib-ng.32fd361/zlib_ng-1.2.11.zlib-ng.32fd361-darwin64-32fd361.tar.zst
+
+ name
+ darwin64
+
+ linux64
+
+ archive
+
+ hash
+ fba88375e12454ae19f4528e11ffc7ddf7d879ec
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-zlib-ng/releases/download/v1.2.11.zlib-ng.32fd361/zlib_ng-1.2.11.zlib-ng.32fd361-linux64-32fd361.tar.zst
+
+ name
+ linux64
+
+ windows64
+
+ archive
+
+ hash
+ ccfca9451063e2d0e95baa73b1ad2054d3e38907
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-zlib-ng/releases/download/v1.2.11.zlib-ng.32fd361/zlib_ng-1.2.11.zlib-ng.32fd361-windows64-32fd361.tar.zst
+
+ name
+ windows64
+
+
+ license
+ zlib-ng
+ license_file
+ LICENSES/zlib-ng.txt
+ copyright
+ Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
+ version
+ 1.2.11.zlib-ng.32fd361
+ name
+ zlib-ng
+ canonical_repo
+ https://bitbucket.org/lindenlab/3p-zlib-ng
+ description
+ zlib data compression library for the next generation systems
package_description
- canonical_repo
- https://github.com/secondlife/viewer
- copyright
- Copyright (c) 2020, Linden Research, Inc.
- description
- Second Life Viewer
- license
- LGPL
- license_file
- docs/LICENSE-source.txt
- name
- Second Life Viewer
platforms
common
@@ -3189,9 +3077,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
RelWithDebInfo
- build
-
-
configure
command
@@ -3204,6 +3089,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
-DINSTALL_PROPRIETARY=TRUE
+ build
+
+
name
RelWithDebInfo
@@ -3211,10 +3099,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
configure
- arguments
-
- ../indra
-
command
cmake
options
@@ -3224,15 +3108,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
-DROOT_PROJECT_NAME:STRING=SecondLife
-DINSTALL_PROPRIETARY=FALSE
+ arguments
+
+ ../indra
+
name
RelWithDebInfoOS
Release
- build
-
-
configure
command
@@ -3245,6 +3130,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
-DINSTALL_PROPRIETARY=TRUE
+ build
+
+
name
Release
@@ -3252,10 +3140,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
configure
- arguments
-
- ../indra
-
command
cmake
options
@@ -3265,6 +3149,10 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
-DROOT_PROJECT_NAME:STRING=SecondLife
-DINSTALL_PROPRIETARY=FALSE
+ arguments
+
+ ../indra
+
name
ReleaseOS
@@ -3275,12 +3163,22 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
darwin64
- build_directory
- build-darwin-x86_64
configurations
RelWithDebInfo
+ configure
+
+ options
+
+ -G
+ Xcode
+
+ arguments
+
+ ../indra
+
+
build
command
@@ -3291,18 +3189,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
RelWithDebInfo
-project
SecondLife.xcodeproj
-
-
- configure
-
- arguments
-
- ../indra
-
- options
-
- -G
- Xcode
+ -parallelizeTargets
default
@@ -3312,6 +3199,14 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
RelWithDebInfoOS
+ configure
+
+ options
+
+ -G
+ Xcode
+
+
build
command
@@ -3322,14 +3217,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
RelWithDebInfo
-project
SecondLife.xcodeproj
-
-
- configure
-
- options
-
- -G
- Xcode
+ -parallelizeTargets
name
@@ -3337,6 +3225,18 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
Release
+ configure
+
+ options
+
+ -G
+ Xcode
+
+ arguments
+
+ ../indra
+
+
build
command
@@ -3347,18 +3247,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
Release
-project
SecondLife.xcodeproj
-
-
- configure
-
- arguments
-
- ../indra
-
- options
-
- -G
- Xcode
+ -parallelizeTargets
name
@@ -3366,6 +3255,14 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
ReleaseOS
+ configure
+
+ options
+
+ -G
+ Xcode
+
+
build
command
@@ -3376,48 +3273,41 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
Release
-project
SecondLife.xcodeproj
-
-
- configure
-
- options
-
- -G
- Xcode
+ -parallelizeTargets
name
ReleaseOS
+ build_directory
+ build-darwin-x86_64
name
darwin64
linux64
- build_directory
- build-linux-x86_64
configurations
Release
- build
-
- command
- ninja
-
configure
- arguments
-
- ../indra
-
options
-G
Ninja
-DLL_TESTS=Off
+ arguments
+
+ ../indra
+
+
+ build
+
+ command
+ ninja
default
True
@@ -3426,11 +3316,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
ReleaseOS
- build
-
- command
- ninja
-
configure
options
@@ -3440,6 +3325,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
-DLL_TESTS=Off
+ build
+
+ command
+ ninja
+
name
ReleaseOS
@@ -3452,23 +3342,33 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
default
+ build_directory
+ build-linux-x86_64
name
linux64
windows
- build_directory
- build-vc${AUTOBUILD_VSVER|170}-$AUTOBUILD_ADDRSIZE
configurations
RelWithDebInfo
- build
+ configure
+ options
+
+ -G
+ ${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN}
+ -A
+ ${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
+
arguments
- SecondLife.sln
+ ..\indra
+
+ build
+
command
devenv
options
@@ -3476,19 +3376,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
/build
RelWithDebInfo|${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
-
- configure
-
arguments
- ..\indra
-
- options
-
- -G
- ${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN}
- -A
- ${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
+ SecondLife.sln
default
@@ -3498,12 +3388,25 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
RelWithDebInfoOS
- build
+ configure
+ options
+
+ -G
+ ${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN}
+ -A
+ ${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
+ -DINSTALL_PROPRIETARY=FALSE
+ -DUSE_KDU=FALSE
+ -DUSE_OPENAL:BOOL=ON
+
arguments
- SecondLife.sln
+ ..\indra
+
+ build
+
command
msbuild.exe
options
@@ -3515,22 +3418,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
/verbosity:minimal
/p:VCBuildAdditionalOptions= /incremental
-
- configure
-
arguments
- ..\indra
-
- options
-
- -G
- ${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN}
- -A
- ${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
- -DINSTALL_PROPRIETARY=FALSE
- -DUSE_KDU=FALSE
- -DUSE_OPENAL:BOOL=ON
+ SecondLife.sln
name
@@ -3538,26 +3428,8 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
Release
- build
-
- arguments
-
- SecondLife.sln
-
- command
- devenv
- options
-
- /build
- Release|${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
-
-
configure
- arguments
-
- ..\indra
-
options
-G
@@ -3565,36 +3437,32 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
-A
${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
+ arguments
+
+ ..\indra
+
+
+ build
+
+ command
+ devenv
+ options
+
+ /build
+ Release|${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
+
+ arguments
+
+ SecondLife.sln
+
name
Release
ReleaseOS
- build
-
- arguments
-
- SecondLife.sln
-
- command
- msbuild.exe
- options
-
- /p:Configuration=Release
- /p:Platform=${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
- /t:Build
- /p:useenv=true
- /verbosity:minimal
- /p:VCBuildAdditionalOptions= /incremental
-
-
configure
- arguments
-
- ..\indra
-
options
-G
@@ -3606,21 +3474,53 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
-DUSE_KDU=FALSE
-DUSE_OPENAL:BOOL=ON
+ arguments
+
+ ..\indra
+
+
+ build
+
+ command
+ msbuild.exe
+ options
+
+ /p:Configuration=Release
+ /p:Platform=${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
+ /t:Build
+ /p:useenv=true
+ /verbosity:minimal
+ /p:VCBuildAdditionalOptions= /incremental
+
+ arguments
+
+ SecondLife.sln
+
name
ReleaseOS
+ build_directory
+ build-vc${AUTOBUILD_VSVER|170}-$AUTOBUILD_ADDRSIZE
name
windows
+ license
+ LGPL
+ license_file
+ docs/LICENSE-source.txt
+ copyright
+ Copyright (c) 2020, Linden Research, Inc.
version_file
newview/viewer_version.txt
+ name
+ Second Life Viewer
+ canonical_repo
+ https://github.com/secondlife/viewer
+ description
+ Second Life Viewer
- type
- autobuild
- version
- 1.3
diff --git a/build.sh b/build.sh
index 89609a9ffd..22f9e0c78a 100755
--- a/build.sh
+++ b/build.sh
@@ -16,6 +16,8 @@
# * The special style in which python is invoked is intentional to permit
# use of a native python install on windows - which requires paths in DOS form
+cleanup="true"
+
retry_cmd()
{
max_attempts="$1"; shift
@@ -110,6 +112,34 @@ installer_CYGWIN()
fi
}
+[[ -n "$GITHUB_OUTPUT" ]] || fatal "Need to export GITHUB_OUTPUT"
+# The following is based on the Warning for GitHub multiline output strings:
+# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
+EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
+
+# Build up these arrays as we go
+metadata=()
+symbolfile=()
+physicstpv=()
+# and dump them to GITHUB_OUTPUT when done
+cleanup="$cleanup ; \
+arrayoutput metadata ; \
+arrayoutput symbolfile ; \
+arrayoutput physicstpv"
+trap "$cleanup" EXIT
+
+arrayoutput()
+{
+ local outputname="$1"
+ # append "[*]" to the array name so array indirection works
+ local array="$1[*]"
+ local IFS='
+'
+ echo "$outputname<<$EOF
+${!array}
+$EOF" >> "$GITHUB_OUTPUT"
+}
+
pre_build()
{
local variant="$1"
@@ -121,7 +151,7 @@ pre_build()
RELEASE_CRASH_REPORTING=ON
HAVOK=ON
SIGNING=()
- if [ "$arch" == "Darwin" -a "$variant" == "Release" ]
+ if [[ "$arch" == "Darwin" && "$variant" == "Release" ]]
then SIGNING=("-DENABLE_SIGNING:BOOL=YES" \
"-DSIGNING_IDENTITY:STRING=Developer ID Application: Linden Research, Inc.")
fi
@@ -145,15 +175,27 @@ pre_build()
VIEWER_SYMBOL_FILE="$(native_path "$abs_build_dir/newview/$variant/secondlife-symbols-$symplat-${AUTOBUILD_ADDRSIZE}.tar.bz2")"
fi
- # don't spew credentials into build log
- bugsplat_sh="$build_secrets_checkout/bugsplat/bugsplat.sh"
- set +x
- if [ -r "$bugsplat_sh" ]
- then # show that we're doing this, just not the contents
- echo source "$bugsplat_sh"
- source "$bugsplat_sh"
+ # expect these variables to be set in the environment from GitHub secrets
+ if [[ -n "$BUGSPLAT_DB" ]]
+ then
+ # don't spew credentials into build log
+ set +x
+ if [[ -z "$BUGSPLAT_USER" || -z "$BUGSPLAT_PASS" ]]
+ then
+ # older mechanism involving build-secrets repo -
+ # if build_secrets_checkout isn't set, report its name
+ bugsplat_sh="${build_secrets_checkout:-\$build_secrets_checkout}/bugsplat/bugsplat.sh"
+ if [ -r "$bugsplat_sh" ]
+ then # show that we're doing this, just not the contents
+ echo source "$bugsplat_sh"
+ source "$bugsplat_sh"
+ else
+ fatal "BUGSPLAT_USER or BUGSPLAT_PASS missing, and no $bugsplat_sh"
+ fi
+ fi
+ set -x
+ export BUGSPLAT_USER BUGSPLAT_PASS
fi
- set -x
# honor autobuild_configure_parameters same as sling-buildscripts
eval_autobuild_configure_parameters=$(eval $(echo echo $autobuild_configure_parameters))
@@ -181,13 +223,17 @@ package_llphysicsextensions_tpv()
# nat 2016-12-21: without HAVOK, can't build PhysicsExtensions_TPV.
if [ "$variant" = "Release" -a "${HAVOK:-}" != "OFF" ]
then
- test -r "$build_dir/packages/llphysicsextensions/autobuild-tpv.xml" || fatal "No llphysicsextensions_tpv autobuild configuration found"
- tpvconfig=$(native_path "$build_dir/packages/llphysicsextensions/autobuild-tpv.xml")
- "$autobuild" build --quiet --config-file "$tpvconfig" -c Tpv || fatal "failed to build llphysicsextensions_tpv"
+ tpvconfig="$build_dir/packages/llphysicsextensions/autobuild-tpv.xml"
+ test -r "$tpvconfig" || fatal "No llphysicsextensions_tpv autobuild configuration found"
+ # SL-19942: autobuild ignores -c switch if AUTOBUILD_CONFIGURATION set
+ unset AUTOBUILD_CONFIGURATION
+ "$autobuild" build --quiet --config-file "$(native_path "$tpvconfig")" -c Tpv \
+ || fatal "failed to build llphysicsextensions_tpv"
# capture the package file name for use in upload later...
PKGTMP=`mktemp -t pgktpv.XXXXXX`
- trap "rm $PKGTMP* 2>/dev/null" 0
+ cleanup="$cleanup ; rm $PKGTMP* 2>/dev/null"
+ trap "$cleanup" EXIT
"$autobuild" package --quiet --config-file "$tpvconfig" --results-file "$(native_path $PKGTMP)" || fatal "failed to package llphysicsextensions_tpv"
tpv_status=$?
if [ -r "${PKGTMP}" ]
@@ -313,12 +359,20 @@ begin_section "coding policy check"
# this far. Running coding policy checks on one platform *should* suffice...
if [[ "$arch" == "Darwin" ]]
then
- # install the git-hooks dependencies
- pip install -r "$(native_path "$git_hooks_checkout/requirements.txt")" || \
- fatal "pip install git-hooks failed"
- # validate the branch we're about to build
- python_cmd "$git_hooks_checkout/coding_policy_git.py" --all_files || \
- fatal "coding policy check failed"
+ git_hooks_reqs="$git_hooks_checkout/requirements.txt"
+ if [[ -r "$(shell_path "$git_hooks_reqs")" ]]
+ then
+ # install the git-hooks dependencies
+ pip install -r "$(native_path "$git_hooks_reqs")" || \
+ fatal "pip install git-hooks failed"
+ fi
+ git_hooks_script="$git_hooks_checkout/coding_policy_git.py"
+ if [[ -r "$(shell_path "$git_hooks_script")" ]]
+ then
+ # validate the branch we're about to build
+ python_cmd "$(native_path "$git_hooks_script")" --all_files || \
+ fatal "coding policy check failed"
+ fi
fi
end_section "coding policy check"
@@ -353,6 +407,7 @@ do
begin_section "Autobuild metadata"
python_cmd "$helpers/codeticket.py" addoutput "Autobuild Metadata" "$build_dir/autobuild-package.xml" --mimetype text/xml \
|| fatal "Upload of autobuild metadata failed"
+ metadata+=("$build_dir/autobuild-package.xml")
if [ "$arch" != "Linux" ]
then
record_dependencies_graph "$build_dir/autobuild-package.xml" # defined in buildscripts/hg/bin/build.sh
@@ -366,8 +421,11 @@ do
if [ -r "$build_dir/newview/viewer_version.txt" ]
then
begin_section "Viewer Version"
- python_cmd "$helpers/codeticket.py" addoutput "Viewer Version" "$(<"$build_dir/newview/viewer_version.txt")" --mimetype inline-text \
+ viewer_version="$(<"$build_dir/newview/viewer_version.txt")"
+ python_cmd "$helpers/codeticket.py" addoutput "Viewer Version" "$viewer_version" --mimetype inline-text \
|| fatal "Upload of viewer version failed"
+ metadata+=("$build_dir/newview/viewer_version.txt")
+ echo "viewer_version=$viewer_version" >> "$GITHUB_OUTPUT"
end_section "Viewer Version"
fi
;;
@@ -376,12 +434,14 @@ do
then
record_event "Doxygen warnings generated; see doxygen_warnings.log"
python_cmd "$helpers/codeticket.py" addoutput "Doxygen Log" "$build_dir/doxygen_warnings.log" --mimetype text/plain ## TBD
+ metadata+=("$build_dir/doxygen_warnings.log")
fi
if [ -d "$build_dir/doxygen/html" ]
then
tar -c -f "$build_dir/viewer-doxygen.tar.bz2" --strip-components 3 "$build_dir/doxygen/html"
python_cmd "$helpers/codeticket.py" addoutput "Doxygen Tarball" "$build_dir/viewer-doxygen.tar.bz2" \
|| fatal "Upload of doxygen tarball failed"
+ metadata+=("$build_dir/viewer-doxygen.tar.bz2")
fi
;;
*)
@@ -486,64 +546,29 @@ then
if $build_viewer
then
begin_section "Uploads"
- # Upload installer
- package=$(installer_$arch)
- if [ x"$package" = x ] || test -d "$package"
+ # nat 2016-12-22: without RELEASE_CRASH_REPORTING, we have no symbol file.
+ if [ "${RELEASE_CRASH_REPORTING:-}" != "OFF" ]
then
- fatal "No installer found from `pwd`"
- succeeded=$build_coverity
- else
- # Upload base package.
- retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput Installer "$package" \
- || fatal "Upload of installer failed"
- wait_for_codeticket
-
- # Upload additional packages.
- for package_id in $additional_packages
- do
- package=$(installer_$arch "$package_id")
- if [ x"$package" != x ]
+ # BugSplat wants to see xcarchive.zip
+ # e.g. build-darwin-x86_64/newview/Release/Second Life Test.xcarchive.zip
+ symbol_file="${build_dir}/newview/${variant}/${viewer_channel}.xcarchive.zip"
+ if [[ ! -f "$symbol_file" ]]
then
- retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput "Installer $package_id" "$package" \
- || fatal "Upload of installer $package_id failed"
- wait_for_codeticket
- else
- record_failure "Failed to find additional package for '$package_id'."
+ # symbol tarball we prep for (e.g.) Breakpad
+ symbol_file="$VIEWER_SYMBOL_FILE"
fi
- done
+ # Upload crash reporter file
+ symbolfile+=("$symbol_file")
+ fi
- if [ "$last_built_variant" = "Release" ]
- then
- # nat 2016-12-22: without RELEASE_CRASH_REPORTING, we have no symbol file.
- if [ "${RELEASE_CRASH_REPORTING:-}" != "OFF" ]
- then
- # Upload crash reporter file
- retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput "Symbolfile" "$VIEWER_SYMBOL_FILE" \
- || fatal "Upload of symbolfile failed"
- wait_for_codeticket
- fi
-
- # Upload the llphysicsextensions_tpv package, if one was produced
- # *TODO: Make this an upload-extension
- if [ -r "$build_dir/llphysicsextensions_package" ]
- then
- llphysicsextensions_package=$(cat $build_dir/llphysicsextensions_package)
- retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput "Physics Extensions Package" "$llphysicsextensions_package" --private \
- || fatal "Upload of physics extensions package failed"
- fi
- fi
-
- # Run upload extensions
- # Ex: bugsplat
- if [ -d ${build_dir}/packages/upload-extensions ]; then
- for extension in ${build_dir}/packages/upload-extensions/*.sh; do
- begin_section "Upload Extension $extension"
- . $extension
- [ $? -eq 0 ] || fatal "Upload of extension $extension failed"
- wait_for_codeticket
- end_section "Upload Extension $extension"
- done
- fi
+ # Upload the llphysicsextensions_tpv package, if one was produced
+ # Only upload this package when building the private repo so the
+ # artifact is private.
+ if [[ "x$GITHUB_REPOSITORY" == "xsecondlife/viewer-private" && \
+ -r "$build_dir/llphysicsextensions_package" ]]
+ then
+ llphysicsextensions_package=$(cat $build_dir/llphysicsextensions_package)
+ physicstpv+=("$llphysicsextensions_package")
fi
end_section "Uploads"
else
diff --git a/buildscripts_support_functions b/buildscripts_support_functions
new file mode 100644
index 0000000000..557d2f80fb
--- /dev/null
+++ b/buildscripts_support_functions
@@ -0,0 +1,60 @@
+# standalone functions from sling-buildscripts
+
+set_build_number_to_revision()
+{
+ record_event "buildNumber $revision"
+}
+
+record_event()
+{
+ echo "=== $@"
+}
+
+begin_section()
+{
+ record_event "START $*"
+ sections+=("$*")
+}
+
+end_section()
+{
+ # accommodate dumb Mac bash 3, which doesn't understand array[-1]
+ local last=$(( ${#sections[@]} - 1 ))
+ record_event "END ${*:-${sections[$last]}}"
+ unset "sections[$last]"
+}
+
+record_success()
+{
+ record_event "SUCCESS $*"
+}
+
+record_failure()
+{
+ record_event "FAILURE $*" >&2
+}
+
+fatal()
+{
+ record_failure "$@"
+ finalize false
+ exit 1
+}
+
+# redefined fail for backward compatibility
+alias fail=fatal
+
+pass()
+{
+ exit 0
+}
+
+export -f set_build_number_to_revision
+export -f record_event
+export -f begin_section
+export -f end_section
+export -f record_success
+export -f record_failure
+export -f fatal
+export -f pass
+export sections
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 86b6ecf3a8..e6c2e7cb70 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -19,6 +19,7 @@ Agathos Frascati
CT-317
CT-352
Ai Austin
+ SL-19399
Aiko Ying
Aimee Trescothick
SNOW-227
@@ -1421,6 +1422,7 @@ Sovereign Engineer
SL-18497
SL-18525
SL-18534
+ SL-19690
SL-19336
SpacedOut Frye
VWR-34
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index c708199309..24534c98d9 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -26,6 +26,11 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} $ENV{LL_BUILD}")
# Portable compilation flags.
add_compile_definitions( ADDRESS_SIZE=${ADDRESS_SIZE})
+# Because older versions of Boost.Bind dumped placeholders _1, _2 et al. into
+# the global namespace, Boost now requires either BOOST_BIND_NO_PLACEHOLDERS
+# to avoid that or BOOST_BIND_GLOBAL_PLACEHOLDERS to state that we require it
+# -- which we do. Without one or the other, we get a ton of Boost warnings.
+add_compile_definitions(BOOST_BIND_GLOBAL_PLACEHOLDERS)
# Configure crash reporting
set(RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in release builds")
@@ -55,15 +60,6 @@ if (WINDOWS)
# http://www.cmake.org/pipermail/cmake/2009-September/032143.html
string(REPLACE "/Zm1000" " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
- # Without PreferredToolArchitecture=x64, as of 2020-06-26 the 32-bit
- # compiler on our TeamCity build hosts has started running out of virtual
- # memory for the precompiled header file.
- # CP changed to only append the flag for 32bit builds - on 64bit builds,
- # locally at least, the build output is spammed with 1000s of 'D9002'
- # warnings about this switch being ignored.
- if(ADDRESS_SIZE EQUAL 32 AND DEFINED ENV{"TEAMCITY_PROJECT_NAME"})
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64")
- endif()
# zlib has assembly-language object files incompatible with SAFESEH
add_link_options(/LARGEADDRESSAWARE
/SAFESEH:NO
@@ -191,3 +187,4 @@ if (LINUX OR DARWIN)
endif (LINUX OR DARWIN)
+
diff --git a/indra/cmake/APR.cmake b/indra/cmake/APR.cmake
index 8a0939c92c..21139319c3 100644
--- a/indra/cmake/APR.cmake
+++ b/indra/cmake/APR.cmake
@@ -16,7 +16,6 @@ if (WINDOWS)
endif (LLCOMMON_LINK_SHARED)
target_link_libraries( ll::apr INTERFACE
${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}apr-1.lib
- ${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}apriconv-1.lib
${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}aprutil-1.lib
)
elseif (DARWIN)
@@ -37,7 +36,6 @@ else (WINDOWS)
target_link_libraries( ll::apr INTERFACE
apr-1
aprutil-1
- iconv
uuid
rt
)
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 286ef3d411..05c51c018d 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -65,6 +65,7 @@ set(cmake_SOURCE_FILES
VisualLeakDetector.cmake
LibVLCPlugin.cmake
XmlRpcEpi.cmake
+ xxHash.cmake
ZLIBNG.cmake
)
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index ae15e8be34..def0c5d6bc 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -57,7 +57,6 @@ if(WINDOWS)
openjp2.dll
libapr-1.dll
libaprutil-1.dll
- libapriconv-1.dll
nghttp2.dll
libhunspell.dll
uriparser.dll
@@ -181,7 +180,6 @@ elseif(DARWIN)
libndofdev.dylib
libnghttp2.dylib
libnghttp2.14.dylib
- libnghttp2.14.19.0.dylib
liburiparser.dylib
liburiparser.1.dylib
liburiparser.1.0.27.dylib
diff --git a/indra/cmake/FMODSTUDIO.cmake b/indra/cmake/FMODSTUDIO.cmake
index c5b21ac4e5..9a1cdff6cb 100644
--- a/indra/cmake/FMODSTUDIO.cmake
+++ b/indra/cmake/FMODSTUDIO.cmake
@@ -2,7 +2,7 @@
include_guard()
-# FMODSTUDIO can be set when launching the make using the argument -DFMODSTUDIO:BOOL=ON
+# FMODSTUDIO can be set when launching the make using the argument -DUSE_FMODSTUDIO:BOOL=ON
# When building using proprietary binaries though (i.e. having access to LL private servers),
# we always build with FMODSTUDIO.
if (INSTALL_PROPRIETARY)
diff --git a/indra/cmake/GLEXT.cmake b/indra/cmake/GLEXT.cmake
index 434b6f0ee8..a780966f0c 100644
--- a/indra/cmake/GLEXT.cmake
+++ b/indra/cmake/GLEXT.cmake
@@ -3,9 +3,7 @@ include(Prebuilt)
include(GLH)
add_library( ll::glext INTERFACE IMPORTED )
-if (WINDOWS OR LINUX)
- use_system_binary(glext)
- use_prebuilt_binary(glext)
-endif (WINDOWS OR LINUX)
+use_system_binary(glext)
+use_prebuilt_binary(glext)
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index bf569e5d99..2172b56da2 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -126,6 +126,13 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
message("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_CFLAGS ${${name}_test_additional_CFLAGS}")
endif()
+ if (DARWIN)
+ # test binaries always need to be signed for local development
+ set_target_properties(PROJECT_${project}_TEST_${name}
+ PROPERTIES
+ XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "-")
+ endif ()
+
#
# Setup test targets
#
@@ -221,6 +228,13 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
)
endif ()
+ if (DARWIN)
+ # test binaries always need to be signed for local development
+ set_target_properties(INTEGRATION_TEST_${testname}
+ PROPERTIES
+ XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "-")
+ endif ()
+
# Add link deps to the executable
if(TEST_DEBUG)
message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})")
diff --git a/indra/cmake/LLMath.cmake b/indra/cmake/LLMath.cmake
index a707c75bc4..e841d2ac78 100644
--- a/indra/cmake/LLMath.cmake
+++ b/indra/cmake/LLMath.cmake
@@ -1,2 +1,5 @@
# -*- cmake -*-
+include(Variables)
+include(Mikktspace)
+
diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake
index 4a501f420b..1ce21c11f9 100644
--- a/indra/cmake/Linking.cmake
+++ b/indra/cmake/Linking.cmake
@@ -62,6 +62,7 @@ elseif (WINDOWS)
user32
ole32
dbghelp
+ rpcrt4.lib
legacy_stdio_definitions
)
else()
diff --git a/indra/cmake/Mikktspace.cmake b/indra/cmake/Mikktspace.cmake
new file mode 100644
index 0000000000..9fd2becba4
--- /dev/null
+++ b/indra/cmake/Mikktspace.cmake
@@ -0,0 +1,6 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+if (NOT USESYSTEMLIBS)
+ use_prebuilt_binary(mikktspace)
+endif (NOT USESYSTEMLIBS)
diff --git a/indra/cmake/TinyGLTF.cmake b/indra/cmake/TinyGLTF.cmake
new file mode 100644
index 0000000000..bb731637a0
--- /dev/null
+++ b/indra/cmake/TinyGLTF.cmake
@@ -0,0 +1,7 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+use_prebuilt_binary(tinygltf)
+
+set(TINYGLTF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/tinygltf)
+
diff --git a/indra/cmake/Tracy.cmake b/indra/cmake/Tracy.cmake
index b3de06a876..32c02edb93 100644
--- a/indra/cmake/Tracy.cmake
+++ b/indra/cmake/Tracy.cmake
@@ -11,8 +11,9 @@ if (USE_TRACY)
use_prebuilt_binary(tracy)
target_include_directories( ll::tracy SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/tracy)
+ target_link_libraries( ll::tracy INTERFACE TracyClient )
-# See: indra/llcommon/llprofiler.h
- target_compile_definitions(ll::tracy INTERFACE LL_PROFILER_CONFIGURATION=3 )
+ # See: indra/llcommon/llprofiler.h
+ add_compile_definitions(LL_PROFILER_CONFIGURATION=3)
endif (USE_TRACY)
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index e6285ab48b..af1f16d04d 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -33,7 +33,7 @@ set(LIBS_OPEN_PREFIX)
set(SCRIPTS_PREFIX ../scripts)
set(VIEWER_PREFIX)
set(INTEGRATION_TESTS_PREFIX)
-set(LL_TESTS ON CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation")
+set(LL_TESTS OFF CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation")
set(INCREMENTAL_LINK OFF CACHE BOOL "Use incremental linking on win32 builds (enable for faster links on some machines)")
set(ENABLE_MEDIA_PLUGINS ON CACHE BOOL "Turn off building media plugins if they are imported by third-party library mechanism")
set(VIEWER_SYMBOL_FILE "" CACHE STRING "Name of tarball into which to place symbol files")
@@ -173,13 +173,17 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL "${CMAKE_MATCH_1}")
message(STATUS "CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL = '${CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL}'")
- string(REGEX MATCHALL "[^ ]+" LL_BUILD_LIST "$ENV{LL_BUILD}")
- list(FIND LL_BUILD_LIST "-iwithsysroot" sysroot_idx)
- if ("${sysroot_idx}" LESS 0)
- message(FATAL_ERROR "Environment variable LL_BUILD must contain '-iwithsysroot'")
- endif ()
- math(EXPR sysroot_idx "${sysroot_idx} + 1")
- list(GET LL_BUILD_LIST "${sysroot_idx}" CMAKE_OSX_SYSROOT)
+ # allow disabling this check by setting LL_SKIP_REQUIRE_SYSROOT either ON as cmake cache var or non-empty as environment var
+ set(LL_SKIP_REQUIRE_SYSROOT OFF CACHE BOOL "Skip requirement to set toolchain sysroot ahead of time. Not skipped by default for consistency, but skipping can be useful for selecting alternative xcode versions side by side")
+ if("$ENV{LL_SKIP_REQUIRE_SYSROOT}" STREQUAL "" AND NOT ${LL_SKIP_REQUIRE_SYSROOT})
+ string(REGEX MATCHALL "[^ ]+" LL_BUILD_LIST "$ENV{LL_BUILD}")
+ list(FIND LL_BUILD_LIST "-iwithsysroot" sysroot_idx)
+ if ("${sysroot_idx}" LESS 0)
+ message(FATAL_ERROR "Environment variable LL_BUILD must contain '-iwithsysroot'")
+ endif ()
+ math(EXPR sysroot_idx "${sysroot_idx} + 1")
+ list(GET LL_BUILD_LIST "${sysroot_idx}" CMAKE_OSX_SYSROOT)
+ endif()
message(STATUS "CMAKE_OSX_SYSROOT = '${CMAKE_OSX_SYSROOT}'")
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0")
diff --git a/indra/cmake/VulkanGltf.cmake b/indra/cmake/VulkanGltf.cmake
new file mode 100644
index 0000000000..94541d5307
--- /dev/null
+++ b/indra/cmake/VulkanGltf.cmake
@@ -0,0 +1,5 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+use_prebuilt_binary(vulkan_gltf)
+
diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py
index 820f356dae..bcb9d884c3 100755
--- a/indra/lib/python/indra/util/llmanifest.py
+++ b/indra/lib/python/indra/util/llmanifest.py
@@ -38,6 +38,7 @@ import itertools
import operator
import os
import re
+import shlex
import shutil
import subprocess
import sys
@@ -531,15 +532,15 @@ class LLManifest(object, metaclass=LLManifestRegistry):
self.cmakedirs(path)
return path
- def run_command(self, command):
+ def run_command(self, command, **kwds):
"""
Runs an external command.
Raises ManifestError exception if the command returns a nonzero status.
"""
- print("Running command:", command)
+ print("Running command:", shlex.join(command))
sys.stdout.flush()
try:
- subprocess.check_call(command)
+ subprocess.check_call(command, **kwds)
except subprocess.CalledProcessError as err:
raise ManifestError( "Command %s returned non-zero status (%s)"
% (command, err.returncode) )
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index 7946a3e705..18b03c1f89 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -1050,7 +1050,6 @@ BOOL LLAvatarAppearance::loadSkeletonNode ()
mRoot->addChild(mMeshLOD[MESH_ID_UPPER_BODY]);
mRoot->addChild(mMeshLOD[MESH_ID_LOWER_BODY]);
mRoot->addChild(mMeshLOD[MESH_ID_SKIRT]);
- mRoot->addChild(mMeshLOD[MESH_ID_HEAD]);
LLAvatarJoint *skull = (LLAvatarJoint*)mRoot->findJoint("mSkull");
if (skull)
diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
index 6f23b2e04c..ff894eeed3 100644
--- a/indra/llappearance/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -377,7 +377,6 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget*
// clear buffer area to ensure we don't pick up UI elements
{
gGL.flush();
- LLGLDisable no_alpha(GL_ALPHA_TEST);
gAlphaMaskProgram.setMinimumAlpha(0.0f);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4f( 0.f, 0.f, 0.f, 1.f );
@@ -410,7 +409,6 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget*
gGL.flush();
gGL.setSceneBlendType(LLRender::BT_REPLACE);
- LLGLDisable no_alpha(GL_ALPHA_TEST);
gAlphaMaskProgram.setMinimumAlpha(0.f);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@@ -500,7 +498,6 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height,
{
// Set the alpha channel to one (clean up after previous blending)
gGL.flush();
- LLGLDisable no_alpha(GL_ALPHA_TEST);
gAlphaMaskProgram.setMinimumAlpha(0.f);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4f( 0.f, 0.f, 0.f, 1.f );
@@ -1025,7 +1022,6 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LL
BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target)
{
- LLGLEnable color_mat(GL_COLOR_MATERIAL);
// *TODO: Is this correct?
//gPipeline.disableLights();
stop_glerror();
@@ -1112,7 +1108,6 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou
if( tex )
{
bool no_alpha_test = getInfo()->mWriteAllChannels;
- LLGLDisable alpha_test(no_alpha_test ? GL_ALPHA_TEST : 0);
if (no_alpha_test)
{
gAlphaMaskProgram.setMinimumAlpha(0.f);
@@ -1162,7 +1157,6 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou
getInfo()->mStaticImageFileName.empty() &&
color_specified )
{
- LLGLDisable no_alpha(GL_ALPHA_TEST);
gAlphaMaskProgram.setMinimumAlpha(0.000f);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@@ -1260,7 +1254,6 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)
LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask );
if( tex )
{
- LLGLSNoAlphaTest gls_no_alpha_test;
gAlphaMaskProgram.setMinimumAlpha(0.f);
gGL.getTexUnit(0)->bind(tex, TRUE);
gl_rect_2d_simple_tex( width, height );
@@ -1279,7 +1272,6 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)
LLGLTexture* tex = mLocalTextureObject->getImage();
if (tex)
{
- LLGLSNoAlphaTest gls_no_alpha_test;
gAlphaMaskProgram.setMinimumAlpha(0.f);
gGL.getTexUnit(0)->bind(tex);
gl_rect_2d_simple_tex( width, height );
@@ -1316,7 +1308,6 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
// Note: if the first param is a mulitply, multiply against the current buffer's alpha
if( !first_param || !first_param->getMultiplyBlend() )
{
- LLGLDisable no_alpha(GL_ALPHA_TEST);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
// Clear the alpha
@@ -1328,7 +1319,6 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
}
// Accumulate alphas
- LLGLSNoAlphaTest gls_no_alpha_test;
gGL.color4f( 1.f, 1.f, 1.f, 1.f );
for (LLTexLayerParamAlpha* param : mParamAlphaList)
{
@@ -1350,7 +1340,6 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
LLGLTexture* tex = mLocalTextureObject->getImage();
if( tex && (tex->getComponents() == 4) )
{
- LLGLSNoAlphaTest gls_no_alpha_test;
LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode();
gGL.getTexUnit(0)->bind(tex, TRUE);
@@ -1370,7 +1359,6 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
{
if( (tex->getComponents() == 4) || (tex->getComponents() == 1) )
{
- LLGLSNoAlphaTest gls_no_alpha_test;
gGL.getTexUnit(0)->bind(tex, TRUE);
gl_rect_2d_simple_tex( width, height );
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@@ -1387,7 +1375,6 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
// Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO );
if ( !is_approx_equal(layer_color.mV[VW], 1.f) )
{
- LLGLDisable no_alpha(GL_ALPHA_TEST);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4fv(layer_color.mV);
gl_rect_2d_simple( width, height );
@@ -1472,7 +1459,14 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
}
else
{ // platforms with working drivers...
- glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data);
+ // We just want GL_ALPHA, but that isn't supported in OGL core profile 4.
+ static const size_t TEMP_BYTES_PER_PIXEL = 4;
+ U8* temp_data = (U8*)ll_aligned_malloc_32(mem_size * TEMP_BYTES_PER_PIXEL);
+ glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, temp_data);
+ for (size_t pixel = 0; pixel < pixels; pixel++) {
+ alpha_data[pixel] = temp_data[(pixel * TEMP_BYTES_PER_PIXEL) + 3];
+ }
+ ll_aligned_free_32(temp_data);
}
}
else
diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp
index a288c8955a..604e0124cb 100644
--- a/indra/llappearance/lltexlayerparams.cpp
+++ b/indra/llappearance/lltexlayerparams.cpp
@@ -149,7 +149,7 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther)
mCachedProcessedTexture(pOther.mCachedProcessedTexture),
mStaticImageTGA(pOther.mStaticImageTGA),
mStaticImageRaw(pOther.mStaticImageRaw),
- mNeedsCreateTexture(pOther.mNeedsCreateTexture),
+ mNeedsCreateTexture(pOther.mNeedsCreateTexture.load()),
mStaticImageInvalid(pOther.mStaticImageInvalid),
mAvgDistortionVec(pOther.mAvgDistortionVec),
mCachedEffectiveWeight(pOther.mCachedEffectiveWeight)
@@ -344,7 +344,6 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height)
mCachedProcessedTexture->setAddressMode(LLTexUnit::TAM_CLAMP);
}
- LLGLSNoAlphaTest gls_no_alpha_test;
gGL.getTexUnit(0)->bind(mCachedProcessedTexture);
gl_rect_2d_simple_tex(width, height);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@@ -361,7 +360,6 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height)
}
else
{
- LLGLDisable no_alpha(GL_ALPHA_TEST);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4f(0.f, 0.f, 0.f, effective_weight);
gl_rect_2d_simple(width, height);
diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h
index e2440998b3..000f55685e 100644
--- a/indra/llappearance/lltexlayerparams.h
+++ b/indra/llappearance/lltexlayerparams.h
@@ -100,7 +100,7 @@ private:
LLPointer mCachedProcessedTexture;
LLPointer mStaticImageTGA;
LLPointer mStaticImageRaw;
- BOOL mNeedsCreateTexture;
+ std::atomic mNeedsCreateTexture;
BOOL mStaticImageInvalid;
LL_ALIGN_16(LLVector4a mAvgDistortionVec);
F32 mCachedEffectiveWeight;
diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp
index 38a6b41afe..190c5290cb 100755
--- a/indra/llaudio/llaudiodecodemgr.cpp
+++ b/indra/llaudio/llaudiodecodemgr.cpp
@@ -607,40 +607,37 @@ void LLAudioDecodeMgr::Impl::startMoreDecodes()
// Kick off a decode
mDecodes[decode_id] = LLPointer(NULL);
- try
- {
- main_queue->postTo(
- general_queue,
- [decode_id]() // Work done on general queue
+ bool posted = main_queue->postTo(
+ general_queue,
+ [decode_id]() // Work done on general queue
+ {
+ LLPointer decode_state = beginDecodingAndWritingAudio(decode_id);
+
+ if (!decode_state)
{
- LLPointer decode_state = beginDecodingAndWritingAudio(decode_id);
-
- if (!decode_state)
- {
- // Audio decode has errored
- return decode_state;
- }
-
- // Disk write of decoded audio is now in progress off-thread
+ // Audio decode has errored
return decode_state;
- },
- [decode_id, this](LLPointer decode_state) // Callback to main thread
- mutable {
- if (!gAudiop)
- {
- // There is no LLAudioEngine anymore. This might happen if
- // an audio decode is enqueued just before shutdown.
- return;
- }
+ }
- // At this point, we can be certain that the pointer to "this"
- // is valid because the lifetime of "this" is dependent upon
- // the lifetime of gAudiop.
+ // Disk write of decoded audio is now in progress off-thread
+ return decode_state;
+ },
+ [decode_id, this](LLPointer decode_state) // Callback to main thread
+ mutable {
+ if (!gAudiop)
+ {
+ // There is no LLAudioEngine anymore. This might happen if
+ // an audio decode is enqueued just before shutdown.
+ return;
+ }
- enqueueFinishAudio(decode_id, decode_state);
- });
- }
- catch (const LLThreadSafeQueueInterrupt&)
+ // At this point, we can be certain that the pointer to "this"
+ // is valid because the lifetime of "this" is dependent upon
+ // the lifetime of gAudiop.
+
+ enqueueFinishAudio(decode_id, decode_state);
+ });
+ if (! posted)
{
// Shutdown
// Consider making processQueue() do a cleanup instead
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
index a133898969..c045d18c42 100755
--- a/indra/llaudio/llaudioengine.h
+++ b/indra/llaudio/llaudioengine.h
@@ -30,6 +30,7 @@
#include
#include
+#include
#include "v3math.h"
#include "v3dmath.h"
diff --git a/indra/llaudio/llaudioengine_openal.h b/indra/llaudio/llaudioengine_openal.h
index a3cab97cd2..562c96c794 100644
--- a/indra/llaudio/llaudioengine_openal.h
+++ b/indra/llaudio/llaudioengine_openal.h
@@ -42,6 +42,7 @@ class LLAudioEngine_OpenAL : public LLAudioEngine
virtual bool init(void *user_data, const std::string &app_title);
virtual std::string getDriverName(bool verbose);
+ virtual LLStreamingAudioInterface* createDefaultStreamingAudioImpl() const { return nullptr; }
virtual void allocateListener();
virtual void shutdown();
@@ -56,7 +57,6 @@ class LLAudioEngine_OpenAL : public LLAudioEngine
/*virtual*/ void updateWind(LLVector3 direction, F32 camera_altitude);
private:
- void * windDSP(void *newbuffer, int length);
typedef S16 WIND_SAMPLE_T;
LLWindGen *mWindGen;
S16 *mWindBuf;
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 6c571b8e07..7ba937a909 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -17,6 +17,7 @@ include(Tracy)
set(llcommon_SOURCE_FILES
+ commoncontrol.cpp
indra_constants.cpp
llallocator.cpp
llallocator_heap_profile.cpp
@@ -117,6 +118,7 @@ set(llcommon_HEADER_FILES
chrono.h
classic_callback.h
+ commoncontrol.h
ctype_workaround.h
fix_macros.h
indra_constants.h
@@ -173,6 +175,7 @@ set(llcommon_HEADER_FILES
llinitdestroyclass.h
llinitparam.h
llinstancetracker.h
+ llinstancetrackersubclass.h
llkeybind.h
llkeythrottle.h
llleap.h
@@ -246,6 +249,7 @@ set(llcommon_HEADER_FILES
stdtypes.h
stringize.h
threadpool.h
+ threadpool_fwd.h
threadsafeschedule.h
timer.h
tuple.h
diff --git a/indra/llcommon/commoncontrol.cpp b/indra/llcommon/commoncontrol.cpp
new file mode 100644
index 0000000000..81e66baf8c
--- /dev/null
+++ b/indra/llcommon/commoncontrol.cpp
@@ -0,0 +1,106 @@
+/**
+ * @file commoncontrol.cpp
+ * @author Nat Goodspeed
+ * @date 2022-06-08
+ * @brief Implementation for commoncontrol.
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Copyright (c) 2022, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "commoncontrol.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llevents.h"
+#include "llsdutil.h"
+
+LLSD LL::CommonControl::access(const LLSD& params)
+{
+ // We can't actually introduce a link-time dependency on llxml, or on any
+ // global LLControlGroup (*koff* gSavedSettings *koff*) but we can issue a
+ // runtime query. If we're running as part of a viewer with
+ // LLViewerControlListener, we can use that to interact with any
+ // instantiated LLControGroup.
+ LLSD response;
+ {
+ LLEventStream reply("reply");
+ LLTempBoundListener connection = reply.listen("listener",
+ [&response] (const LLSD& event)
+ {
+ response = event;
+ return false;
+ });
+ LLSD rparams{ params };
+ rparams["reply"] = reply.getName();
+ LLEventPumps::instance().obtain("LLViewerControl").post(rparams);
+ }
+ // LLViewerControlListener responds immediately. If it's listening at all,
+ // it will already have set response.
+ if (! response.isDefined())
+ {
+ LLTHROW(NoListener("No LLViewerControl listener instantiated"));
+ }
+ LLSD error{ response["error"] };
+ if (error.isDefined())
+ {
+ LLTHROW(ParamError(error));
+ }
+ response.erase("error");
+ response.erase("reqid");
+ return response;
+}
+
+/// set control group.key to defined default value
+LLSD LL::CommonControl::set_default(const std::string& group, const std::string& key)
+{
+ return access(llsd::map("op", "set",
+ "group", group, "key", key))["value"];
+}
+
+/// set control group.key to specified value
+LLSD LL::CommonControl::set(const std::string& group, const std::string& key, const LLSD& value)
+{
+ return access(llsd::map("op", "set",
+ "group", group, "key", key, "value", value))["value"];
+}
+
+/// toggle boolean control group.key
+LLSD LL::CommonControl::toggle(const std::string& group, const std::string& key)
+{
+ return access(llsd::map("op", "toggle",
+ "group", group, "key", key))["value"];
+}
+
+/// get the definition for control group.key, (! isDefined()) if bad
+/// ["name"], ["type"], ["value"], ["comment"]
+LLSD LL::CommonControl::get_def(const std::string& group, const std::string& key)
+{
+ return access(llsd::map("op", "get",
+ "group", group, "key", key));
+}
+
+/// get the value of control group.key
+LLSD LL::CommonControl::get(const std::string& group, const std::string& key)
+{
+ return access(llsd::map("op", "get",
+ "group", group, "key", key))["value"];
+}
+
+/// get defined groups
+std::vector LL::CommonControl::get_groups()
+{
+ auto groups{ access(llsd::map("op", "groups"))["groups"] };
+ return { groups.beginArray(), groups.endArray() };
+}
+
+/// get definitions for all variables in group
+LLSD LL::CommonControl::get_vars(const std::string& group)
+{
+ return access(llsd::map("op", "vars", "group", group))["vars"];
+}
diff --git a/indra/llcommon/commoncontrol.h b/indra/llcommon/commoncontrol.h
new file mode 100644
index 0000000000..07d4a45ac5
--- /dev/null
+++ b/indra/llcommon/commoncontrol.h
@@ -0,0 +1,75 @@
+/**
+ * @file commoncontrol.h
+ * @author Nat Goodspeed
+ * @date 2022-06-08
+ * @brief Access LLViewerControl LLEventAPI, if process has one.
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Copyright (c) 2022, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_COMMONCONTROL_H)
+#define LL_COMMONCONTROL_H
+
+#include
+#include "llexception.h"
+#include "llsd.h"
+
+namespace LL
+{
+ class CommonControl
+ {
+ public:
+ struct Error: public LLException
+ {
+ Error(const std::string& what): LLException(what) {}
+ };
+
+ /// Exception thrown if there's no LLViewerControl LLEventAPI
+ struct NoListener: public Error
+ {
+ NoListener(const std::string& what): Error(what) {}
+ };
+
+ struct ParamError: public Error
+ {
+ ParamError(const std::string& what): Error(what) {}
+ };
+
+ /// set control group.key to defined default value
+ static
+ LLSD set_default(const std::string& group, const std::string& key);
+
+ /// set control group.key to specified value
+ static
+ LLSD set(const std::string& group, const std::string& key, const LLSD& value);
+
+ /// toggle boolean control group.key
+ static
+ LLSD toggle(const std::string& group, const std::string& key);
+
+ /// get the definition for control group.key, (! isDefined()) if bad
+ /// ["name"], ["type"], ["value"], ["comment"]
+ static
+ LLSD get_def(const std::string& group, const std::string& key);
+
+ /// get the value of control group.key
+ static
+ LLSD get(const std::string& group, const std::string& key);
+
+ /// get defined groups
+ static
+ std::vector get_groups();
+
+ /// get definitions for all variables in group
+ static
+ LLSD get_vars(const std::string& group);
+
+ private:
+ static
+ LLSD access(const LLSD& params);
+ };
+} // namespace LL
+
+#endif /* ! defined(LL_COMMONCONTROL_H) */
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 435531f86f..e49f72722b 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -522,6 +522,7 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
//static
S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
{
+ LL_PROFILE_ZONE_SCOPED;
//*****************************************
LLAPRFilePoolScope scope(pool);
apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), APR_READ|APR_BINARY);
@@ -566,6 +567,7 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb
//static
S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
{
+ LL_PROFILE_ZONE_SCOPED;
apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
if (offset < 0)
{
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index 4c84223dad..6492d888c1 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -96,6 +96,7 @@ LLAssetDictionary::LLAssetDictionary()
addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false));
addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false));
addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", true, true, true));
+ addEntry(LLAssetType::AT_MATERIAL, new AssetEntry("MATERIAL", "material", "render material", true, true, true));
addEntry(LLAssetType::AT_UNKNOWN, new AssetEntry("UNKNOWN", "invalid", NULL, false, false, false));
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE));
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 652c548d59..e8df8574f7 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -127,8 +127,9 @@ public:
AT_RESERVED_6 = 55,
AT_SETTINGS = 56, // Collection of settings
-
- AT_COUNT = 57,
+ AT_MATERIAL = 57, // Render Material
+
+ AT_COUNT = 58,
// +*********************************************************+
// | TO ADD AN ELEMENT TO THIS ENUM: |
diff --git a/indra/llcommon/llcallstack.h b/indra/llcommon/llcallstack.h
index 5acf04a49f..d5a2b7b157 100644
--- a/indra/llcommon/llcallstack.h
+++ b/indra/llcommon/llcallstack.h
@@ -79,9 +79,9 @@ struct LLContextStatus
LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLContextStatus& context_status);
-#define dumpStack(tag) \
- if (debugLoggingEnabled(tag)) \
- { \
- LLCallStack cs; \
- LL_DEBUGS(tag) << "STACK:\n" << "====================\n" << cs << "====================" << LL_ENDL; \
- }
+#define dumpStack(tag) \
+ LL_DEBUGS(tag) << "STACK:\n" \
+ << "====================\n" \
+ << LLCallStack() \
+ << "====================" \
+ << LL_ENDL;
diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index d2c4e66160..6e988260a9 100644
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -37,12 +37,13 @@ thread_local bool gProfilerEnabled = false;
#if (TRACY_ENABLE)
// Override new/delete for tracy memory profiling
-void *operator new(size_t size)
+
+void* ll_tracy_new(size_t size)
{
void* ptr;
if (gProfilerEnabled)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
+ //LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
ptr = (malloc)(size);
}
else
@@ -57,12 +58,22 @@ void *operator new(size_t size)
return ptr;
}
-void operator delete(void *ptr) noexcept
+void* operator new(size_t size)
+{
+ return ll_tracy_new(size);
+}
+
+void* operator new[](std::size_t count)
+{
+ return ll_tracy_new(count);
+}
+
+void ll_tracy_delete(void* ptr)
{
TracyFree(ptr);
if (gProfilerEnabled)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
+ //LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
(free)(ptr);
}
else
@@ -71,6 +82,16 @@ void operator delete(void *ptr) noexcept
}
}
+void operator delete(void *ptr) noexcept
+{
+ ll_tracy_delete(ptr);
+}
+
+void operator delete[](void* ptr) noexcept
+{
+ ll_tracy_delete(ptr);
+}
+
// C-style malloc/free can't be so easily overridden, so we define tracy versions and use
// a pre-processor #define in linden_common.h to redirect to them. The parens around the native
// functions below prevents recursive substitution by the preprocessor.
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index 70d8dfc8b9..cfaf3415e7 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -123,11 +123,7 @@ LLCoros::LLCoros():
// Previously we used
// boost::context::guarded_stack_allocator::default_stacksize();
// empirically this is insufficient.
-#if ADDRESS_SIZE == 64
- mStackSize(512*1024),
-#else
- mStackSize(256*1024),
-#endif
+ mStackSize(768*1024),
// mCurrent does NOT own the current CoroData instance -- it simply
// points to it. So initialize it with a no-op deleter.
mCurrent{ [](CoroData*){} }
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 02cb186275..414515854a 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -1603,19 +1603,18 @@ namespace LLError
}
}
-bool debugLoggingEnabled(const std::string& tag)
+void crashdriver(void (*callback)(int*))
{
- LLMutexTrylock lock(getMutex(), 5);
- if (!lock.isLocked())
- {
- return false;
- }
+ // The LLERROR_CRASH macro used to have inline code of the form:
+ //int* make_me_crash = NULL;
+ //*make_me_crash = 0;
- SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
- LLError::ELevel level = LLError::LEVEL_DEBUG;
- bool res = checkLevelMap(s->mTagLevelMap, tag, level);
- return res;
+ // But compilers are getting smart enough to recognize that, so we must
+ // assign to an address supplied by a separate source file. We could do
+ // the assignment here in crashdriver() -- but then BugSplat would group
+ // all LL_ERRS() crashes as the fault of this one function, instead of
+ // identifying the specific LL_ERRS() source line. So instead, do the
+ // assignment in a lambda in the caller's source. We just provide the
+ // nullptr target.
+ callback(nullptr);
}
-
-
-
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 020f05e8f5..05dd88ee51 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -82,9 +82,11 @@ const int LL_ERR_NOERR = 0;
#ifdef SHOW_ASSERT
#define llassert(func) llassert_always_msg(func, #func)
+#define llassert_msg(func, msg) llassert_always_msg(func, msg)
#define llverify(func) llassert_always_msg(func, #func)
#else
#define llassert(func)
+#define llassert_msg(func, msg)
#define llverify(func) do {if (func) {}} while(0)
#endif
@@ -383,11 +385,9 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
#define LL_NEWLINE '\n'
// Use this only in LL_ERRS or in a place that LL_ERRS may not be used
-#define LLERROR_CRASH \
-{ \
- int* make_me_crash = NULL;\
- *make_me_crash = 0; \
- exit(*make_me_crash); \
+#define LLERROR_CRASH \
+{ \
+ crashdriver([](int* ptr){ *ptr = 0; exit(*ptr); }); \
}
#define LL_ENDL \
@@ -464,7 +464,32 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
LLError::CallSite& _site(_sites[which]); \
lllog_test_()
-// Check at run-time whether logging is enabled, without generating output
+/*
+// Check at run-time whether logging is enabled, without generating output.
+Resist the temptation to add a function like this because it incurs the
+expense of locking and map-searching every time control reaches it.
bool debugLoggingEnabled(const std::string& tag);
+Instead of:
+
+if debugLoggingEnabled("SomeTag")
+{
+ // ... presumably expensive operation ...
+ LL_DEBUGS("SomeTag") << ... << LL_ENDL;
+}
+
+Use this:
+
+LL_DEBUGS("SomeTag");
+// ... presumably expensive operation ...
+LL_CONT << ...;
+LL_ENDL;
+
+LL_DEBUGS("SomeTag") performs the locking and map-searching ONCE, then caches
+the result in a static variable.
+*/
+
+// used by LLERROR_CRASH
+void crashdriver(void (*)(int*));
+
#endif // LL_LLERROR_H
diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp
index c54029e8b4..1e9920746b 100644
--- a/indra/llcommon/llframetimer.cpp
+++ b/indra/llcommon/llframetimer.cpp
@@ -29,11 +29,6 @@
#include "llframetimer.h"
-// We don't bother building a stand alone lib; we just need to include the one source file for Tracy support
-#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
- #include "TracyClient.cpp"
-#endif // LL_PROFILER_CONFIGURATION
-
// Static members
//LLTimer LLFrameTimer::sInternalTimer;
U64 LLFrameTimer::sStartTotalTime = totalTime();
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 34f2a5985a..27422e1266 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -104,22 +104,26 @@ public:
return LockStatic()->mMap.size();
}
- // snapshot of std::pair> pairs
- class snapshot
+ // snapshot of std::pair> pairs, for
+ // some SUBCLASS derived from T
+ template
+ class snapshot_of
{
// It's very important that what we store in this snapshot are
// weak_ptrs, NOT shared_ptrs. That's how we discover whether any
// instance has been deleted during the lifespan of a snapshot.
typedef std::vector> VectorType;
- // Dereferencing our iterator produces a std::shared_ptr for each
- // instance that still exists. Since we store weak_ptrs, that involves
- // two chained transformations:
+ // Dereferencing the iterator we publish produces a
+ // std::shared_ptr for each instance that still exists.
+ // Since we store weak_ptr, that involves two chained
+ // transformations:
// - a transform_iterator to lock the weak_ptr and return a shared_ptr
- // - a filter_iterator to skip any shared_ptr that has become invalid.
+ // - a filter_iterator to skip any shared_ptr that has become
+ // invalid or references any T instance that isn't SUBCLASS.
// It is very important that we filter lazily, that is, during
// traversal. Any one of our stored weak_ptrs might expire during
// traversal.
- typedef std::pair strong_pair;
+ typedef std::pair> strong_pair;
// Note for future reference: nat has not yet had any luck (up to
// Boost 1.67) trying to use boost::transform_iterator with a hand-
// coded functor, only with actual functions. In my experience, an
@@ -127,7 +131,7 @@ public:
// result_type typedef. But this works.
static strong_pair strengthen(typename VectorType::value_type& pair)
{
- return { pair.first, pair.second.lock() };
+ return { pair.first, std::dynamic_pointer_cast(pair.second.lock()) };
}
static bool dead_skipper(const strong_pair& pair)
{
@@ -135,7 +139,7 @@ public:
}
public:
- snapshot():
+ snapshot_of():
// populate our vector with a snapshot of (locked!) InstanceMap
// note, this assigns pair to pair
mData(mLock->mMap.begin(), mLock->mMap.end())
@@ -184,44 +188,51 @@ public:
#endif // LL_WINDOWS
VectorType mData;
};
+ using snapshot = snapshot_of;
- // iterate over this for references to each instance
- class instance_snapshot: public snapshot
+ // iterate over this for references to each SUBCLASS instance
+ template
+ class instance_snapshot_of: public snapshot_of
{
private:
- static T& instance_getter(typename snapshot::iterator::reference pair)
+ using super = snapshot_of;
+ static T& instance_getter(typename super::iterator::reference pair)
{
return *pair.second;
}
public:
typedef boost::transform_iterator iterator;
- iterator begin() { return iterator(snapshot::begin(), instance_getter); }
- iterator end() { return iterator(snapshot::end(), instance_getter); }
+ typename super::iterator> iterator;
+ iterator begin() { return iterator(super::begin(), instance_getter); }
+ iterator end() { return iterator(super::end(), instance_getter); }
void deleteAll()
{
- for (auto it(snapshot::begin()), end(snapshot::end()); it != end; ++it)
+ for (auto it(super::begin()), end(super::end()); it != end; ++it)
{
delete it->second.get();
}
}
- };
+ };
+ using instance_snapshot = instance_snapshot_of;
// iterate over this for each key
- class key_snapshot: public snapshot
+ template
+ class key_snapshot_of: public snapshot_of
{
private:
- static KEY key_getter(typename snapshot::iterator::reference pair)
+ using super = snapshot_of;
+ static KEY key_getter(typename super::iterator::reference pair)
{
return pair.first;
}
public:
typedef boost::transform_iterator iterator;
- iterator begin() { return iterator(snapshot::begin(), key_getter); }
- iterator end() { return iterator(snapshot::end(), key_getter); }
+ typename super::iterator> iterator;
+ iterator begin() { return iterator(super::begin(), key_getter); }
+ iterator end() { return iterator(super::end(), key_getter); }
};
+ using key_snapshot = key_snapshot_of;
static ptr_t getInstance(const KEY& k)
{
@@ -368,22 +379,25 @@ public:
return LockStatic()->mSet.size();
}
- // snapshot of std::shared_ptr pointers
- class snapshot
+ // snapshot of std::shared_ptr pointers
+ template
+ class snapshot_of
{
// It's very important that what we store in this snapshot are
// weak_ptrs, NOT shared_ptrs. That's how we discover whether any
// instance has been deleted during the lifespan of a snapshot.
typedef std::vector VectorType;
- // Dereferencing our iterator produces a std::shared_ptr for each
- // instance that still exists. Since we store weak_ptrs, that involves
- // two chained transformations:
+ // Dereferencing the iterator we publish produces a
+ // std::shared_ptr for each instance that still exists.
+ // Since we store weak_ptrs, that involves two chained
+ // transformations:
// - a transform_iterator to lock the weak_ptr and return a shared_ptr
- // - a filter_iterator to skip any shared_ptr that has become invalid.
- typedef std::shared_ptr strong_ptr;
+ // - a filter_iterator to skip any shared_ptr that has become invalid
+ // or references any T instance that isn't SUBCLASS.
+ typedef std::shared_ptr strong_ptr;
static strong_ptr strengthen(typename VectorType::value_type& ptr)
{
- return ptr.lock();
+ return std::dynamic_pointer_cast(ptr.lock());
}
static bool dead_skipper(const strong_ptr& ptr)
{
@@ -391,7 +405,7 @@ public:
}
public:
- snapshot():
+ snapshot_of():
// populate our vector with a snapshot of (locked!) InstanceSet
// note, this assigns stored shared_ptrs to weak_ptrs for snapshot
mData(mLock->mSet.begin(), mLock->mSet.end())
@@ -437,22 +451,33 @@ public:
#endif // LL_WINDOWS
VectorType mData;
};
+ using snapshot = snapshot_of;
// iterate over this for references to each instance
- struct instance_snapshot: public snapshot
+ template
+ class instance_snapshot_of: public snapshot_of
{
- typedef boost::indirect_iterator iterator;
- iterator begin() { return iterator(snapshot::begin()); }
- iterator end() { return iterator(snapshot::end()); }
+ private:
+ using super = snapshot_of;
+
+ public:
+ typedef boost::indirect_iterator iterator;
+ iterator begin() { return iterator(super::begin()); }
+ iterator end() { return iterator(super::end()); }
void deleteAll()
{
- for (auto it(snapshot::begin()), end(snapshot::end()); it != end; ++it)
+ for (auto it(super::begin()), end(super::end()); it != end; ++it)
{
delete it->get();
}
}
};
+ using instance_snapshot = instance_snapshot_of;
+ // key_snapshot_of isn't really meaningful, but define it anyway to avoid
+ // requiring two different LLInstanceTrackerSubclass implementations.
+ template
+ using key_snapshot_of = instance_snapshot_of;
protected:
LLInstanceTracker()
diff --git a/indra/llcommon/llinstancetrackersubclass.h b/indra/llcommon/llinstancetrackersubclass.h
new file mode 100644
index 0000000000..ea9a38200f
--- /dev/null
+++ b/indra/llcommon/llinstancetrackersubclass.h
@@ -0,0 +1,98 @@
+/**
+ * @file llinstancetrackersubclass.h
+ * @author Nat Goodspeed
+ * @date 2022-12-09
+ * @brief Intermediate class to get subclass-specific types from
+ * LLInstanceTracker instance-retrieval methods.
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Copyright (c) 2022, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLINSTANCETRACKERSUBCLASS_H)
+#define LL_LLINSTANCETRACKERSUBCLASS_H
+
+#include // std::shared_ptr, std::weak_ptr
+
+/**
+ * Derive your subclass S of a subclass T of LLInstanceTracker from
+ * LLInstanceTrackerSubclass to perform appropriate downcasting and
+ * filtering for LLInstanceTracker access methods.
+ *
+ * LLInstanceTracker uses CRTP, so that getWeak(), getInstance(), snapshot
+ * and instance_snapshot return pointers and references to T. The trouble is
+ * that subclasses T0 and T1 derived from T also get pointers and references
+ * to their base class T, requiring explicit downcasting. Moreover,
+ * T0::getInstance() shouldn't find an instance of any T subclass other than
+ * T0. Nor should T0::snapshot.
+ *
+ * @code
+ * class Tracked: public LLInstanceTracker
+ * {
+ * private:
+ * using super = LLInstanceTracker;
+ * public:
+ * Tracked(const std::string& name): super(name) {}
+ * // All references to Tracked::ptr_t, Tracked::getInstance() etc.
+ * // appropriately use Tracked.
+ * // ...
+ * };
+ *
+ * // But now we derive SubTracked from Tracked. We need SubTracked::ptr_t,
+ * // SubTracked::getInstance() etc. to use SubTracked, not Tracked.
+ * // This LLInstanceTrackerSubclass specialization is itself derived from
+ * // Tracked.
+ * class SubTracked: public LLInstanceTrackerSubclass
+ * {
+ * private:
+ * using super = LLInstanceTrackerSubclass;
+ * public:
+ * // LLInstanceTrackerSubclass's constructor forwards to Tracked's.
+ * SubTracked(const std::string& name): super(name) {}
+ * // SubTracked::getInstance() returns std::shared_ptr, etc.
+ * // ...
+ * @endcode
+ */
+template
+class LLInstanceTrackerSubclass: public T
+{
+public:
+ using ptr_t = std::shared_ptr;
+ using weak_t = std::weak_ptr;
+
+ // forward any constructor call to the corresponding T ctor
+ template
+ LLInstanceTrackerSubclass(ARGS&&... args):
+ T(std::forward(args)...)
+ {}
+
+ weak_t getWeak()
+ {
+ // call base-class getWeak(), try to lock, downcast to SUBCLASS
+ return std::dynamic_pointer_cast(T::getWeak().lock());
+ }
+
+ template
+ static ptr_t getInstance(const KEY& k)
+ {
+ return std::dynamic_pointer_cast(T::getInstance(k));
+ }
+
+ using snapshot = typename T::template snapshot_of;
+ using instance_snapshot = typename T::template instance_snapshot_of;
+ using key_snapshot = typename T::template key_snapshot_of;
+
+ static size_t instanceCount()
+ {
+ // T::instanceCount() lies because our snapshot, et al., won't
+ // necessarily return all the T instances -- only those that are also
+ // SUBCLASS instances. Count those.
+ size_t count = 0;
+ for (const auto& pair : snapshot())
+ ++count;
+ return count;
+ }
+};
+
+#endif /* ! defined(LL_LLINSTANCETRACKERSUBCLASS_H) */
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index 259f5bc505..5b5bf97cef 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -389,6 +389,17 @@ public:
// Read all remaining bytes and log.
LL_INFOS("LLLeap") << mDesc << ": " << rest << LL_ENDL;
}
+ /*--------------------------- diagnostic ---------------------------*/
+ else if (data["eof"].asBoolean())
+ {
+ LL_DEBUGS("LLLeap") << mDesc << " ended, no partial line" << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("LLLeap") << mDesc << " (still running, " << childerr.size()
+ << " bytes pending)" << LL_ENDL;
+ }
+ /*------------------------- end diagnostic -------------------------*/
return false;
}
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index d6ae1284d3..7cdf7254ff 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -35,6 +35,7 @@
# include
# include
# include
+#include
#elif LL_LINUX
# include
#endif
@@ -109,6 +110,50 @@ void LLMemory::updateMemoryInfo()
{
sAvailPhysicalMemInKB = U32Kilobytes(0);
}
+
+#elif defined(LL_DARWIN)
+ task_vm_info info;
+ mach_msg_type_number_t infoCount = TASK_VM_INFO_COUNT;
+ // MACH_TASK_BASIC_INFO reports the same resident_size, but does not tell us the reusable bytes or phys_footprint.
+ if (task_info(mach_task_self(), TASK_VM_INFO, reinterpret_cast(&info), &infoCount) == KERN_SUCCESS)
+ {
+ // Our Windows definition of PagefileUsage is documented by Microsoft as "the total amount of
+ // memory that the memory manager has committed for a running process", which is rss.
+ sAllocatedPageSizeInKB = U32Bytes(info.resident_size);
+
+ // Activity Monitor => Inspect Process => Real Memory Size appears to report resident_size
+ // Activity monitor => main window memory column appears to report phys_footprint, which spot checks as at least 30% less.
+ // I think that is because of compression, which isn't going to give us a consistent measurement. We want uncompressed totals.
+ //
+ // In between is resident_size - reusable. This is what Chrome source code uses, with source comments saying it is 'the "Real Memory" value
+ // reported for the app by the Memory Monitor in Instruments.' It is still about 8% bigger than phys_footprint.
+ //
+ // (On Windows, we use WorkingSetSize.)
+ sAllocatedMemInKB = U32Bytes(info.resident_size - info.reusable);
+ }
+ else
+ {
+ LL_WARNS() << "task_info failed" << LL_ENDL;
+ }
+
+ // Total installed and available physical memory are properties of the host, not just our process.
+ vm_statistics64_data_t vmstat;
+ mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
+ mach_port_t host = mach_host_self();
+ vm_size_t page_size;
+ host_page_size(host, &page_size);
+ kern_return_t result = host_statistics64(host, HOST_VM_INFO64, reinterpret_cast(&vmstat), &count);
+ if (result == KERN_SUCCESS) {
+ // This is what Chrome reports as 'the "Physical Memory Free" value reported by the Memory Monitor in Instruments.'
+ // Note though that inactive pages are not included here and not yet free, but could become so under memory pressure.
+ sAvailPhysicalMemInKB = U32Bytes(vmstat.free_count * page_size);
+ sMaxPhysicalMemInKB = LLMemoryInfo::getHardwareMemSize();
+ }
+ else
+ {
+ LL_WARNS() << "task_info failed" << LL_ENDL;
+ }
+
#else
//not valid for other systems for now.
sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS());
diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h
index 838d7d34c0..0d70da6178 100644
--- a/indra/llcommon/llmutex.h
+++ b/indra/llcommon/llmutex.h
@@ -36,7 +36,8 @@
//============================================================================
-#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
+//#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
+#define MUTEX_DEBUG 0 //disable mutex debugging as it's interfering with profiles
#if MUTEX_DEBUG
#include
@@ -61,7 +62,7 @@ protected:
mutable LLThread::id_t mLockingThread;
#if MUTEX_DEBUG
- std::map mIsLocked;
+ std::unordered_map mIsLocked;
#endif
};
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 9a6453ea48..f9de0c7929 100644
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -340,4 +340,28 @@ private:
bool mStayUnique;
};
+
+// boost hash adapter
+template
+struct boost::hash>
+{
+ typedef LLPointer argument_type;
+ typedef std::size_t result_type;
+ result_type operator()(argument_type const& s) const
+ {
+ return (std::size_t) s.get();
+ }
+};
+
+// Adapt boost hash to std hash
+namespace std
+{
+ template struct hash>
+ {
+ std::size_t operator()(LLPointer const& s) const noexcept
+ {
+ return boost::hash>()(s);
+ }
+ };
+}
#endif
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index 4a1a81f083..28f8bc2b93 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -746,7 +746,7 @@ private:
__cpuid(0x1, eax, ebx, ecx, edx);
if(feature_infos[0] != (S32)edx)
{
- LL_ERRS() << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << LL_ENDL;
+ LL_WARNS() << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << LL_ENDL;
}
#endif // LL_RELEASE_FOR_DOWNLOAD
diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h
index f9d7ae7ce4..af5e5777bf 100644
--- a/indra/llcommon/llprofiler.h
+++ b/indra/llcommon/llprofiler.h
@@ -86,8 +86,12 @@ extern thread_local bool gProfilerEnabled;
#define TRACY_ONLY_IPV4 1
#include "Tracy.hpp"
- // Mutually exclusive with detailed memory tracing
+ // Enable OpenGL profiling
#define LL_PROFILER_ENABLE_TRACY_OPENGL 0
+
+ // Enable RenderDoc labeling
+ #define LL_PROFILER_ENABLE_RENDER_DOC 0
+
#endif
#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY
@@ -104,14 +108,13 @@ extern thread_local bool gProfilerEnabled;
#define LL_PROFILE_ZONE_ERR(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000 ) // RGB yellow
#define LL_PROFILE_ZONE_INFO(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF ) // RGB cyan
#define LL_PROFILE_ZONE_WARN(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 ) // RGB red
- #define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size)
- #define LL_PROFILE_FREE(ptr) TracyFree(ptr)
#endif
#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_FAST_TIMER
#define LL_PROFILER_FRAME_END
#define LL_PROFILER_SET_THREAD_NAME( name ) (void)(name)
#define LL_RECORD_BLOCK_TIME(name) const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(name)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__);
#define LL_PROFILE_ZONE_NAMED(name) // LL_PROFILE_ZONE_NAMED is a no-op when Tracy is disabled
+ #define LL_PROFILE_ZONE_NAMED_COLOR(name,color) // LL_PROFILE_ZONE_NAMED_COLOR is a no-op when Tracy is disabled
#define LL_PROFILE_ZONE_SCOPED // LL_PROFILE_ZONE_SCOPED is a no-op when Tracy is disabled
#define LL_PROFILE_ZONE_COLOR(name,color) // LL_RECORD_BLOCK_TIME(name)
@@ -121,8 +124,6 @@ extern thread_local bool gProfilerEnabled;
#define LL_PROFILE_ZONE_ERR(name) (void)(name); // Not supported
#define LL_PROFILE_ZONE_INFO(name) (void)(name); // Not supported
#define LL_PROFILE_ZONE_WARN(name) (void)(name); // Not supported
- #define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
- #define LL_PROFILE_FREE(ptr) (void)(ptr);
#endif
#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
#define LL_PROFILER_FRAME_END FrameMark
@@ -138,14 +139,45 @@ extern thread_local bool gProfilerEnabled;
#define LL_PROFILE_ZONE_ERR(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000 ) // RGB yellow
#define LL_PROFILE_ZONE_INFO(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF ) // RGB cyan
#define LL_PROFILE_ZONE_WARN(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 ) // RGB red
- #define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size)
- #define LL_PROFILE_FREE(ptr) TracyFree(ptr)
#endif
#else
#define LL_PROFILER_FRAME_END
#define LL_PROFILER_SET_THREAD_NAME( name ) (void)(name)
#endif // LL_PROFILER
+#if LL_PROFILER_ENABLE_TRACY_OPENGL
+#define LL_PROFILE_GPU_ZONE(name) TracyGpuZone(name)
+#define LL_PROFILE_GPU_ZONEC(name,color) TracyGpuZoneC(name,color)
+#define LL_PROFILER_GPU_COLLECT TracyGpuCollect
+#define LL_PROFILER_GPU_CONTEXT TracyGpuContext
+
+// disable memory tracking (incompatible with GPU tracing
+#define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
+#define LL_PROFILE_FREE(ptr) (void)(ptr);
+#else
+#define LL_PROFILE_GPU_ZONE(name) (void)name;
+#define LL_PROFILE_GPU_ZONEC(name,color) (void)name;(void)color;
+#define LL_PROFILER_GPU_COLLECT
+#define LL_PROFILER_GPU_CONTEXT
+
+#define LL_LABEL_OBJECT_GL(type, name, length, label)
+
+#if LL_PROFILER_CONFIGURATION > 1
+#define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size)
+#define LL_PROFILE_FREE(ptr) TracyFree(ptr)
+#else
+#define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
+#define LL_PROFILE_FREE(ptr) (void)(ptr);
+#endif
+
+#endif
+
+#if LL_PROFILER_ENABLE_RENDER_DOC
+#define LL_LABEL_OBJECT_GL(type, name, length, label) glObjectLabel(type, name, length, label)
+#else
+#define LL_LABEL_OBJECT_GL(type, name, length, label)
+#endif
+
#include "llprofilercategories.h"
#endif // LL_PROFILER_H
diff --git a/indra/llcommon/llprofilercategories.h b/indra/llcommon/llprofilercategories.h
index 8db29468cc..617431f629 100644
--- a/indra/llcommon/llprofilercategories.h
+++ b/indra/llcommon/llprofilercategories.h
@@ -52,7 +52,7 @@
#define LL_PROFILER_CATEGORY_ENABLE_LOGGING 1
#define LL_PROFILER_CATEGORY_ENABLE_MATERIAL 1
#define LL_PROFILER_CATEGORY_ENABLE_MEDIA 1
-#define LL_PROFILER_CATEGORY_ENABLE_MEMORY 1
+#define LL_PROFILER_CATEGORY_ENABLE_MEMORY 0
#define LL_PROFILER_CATEGORY_ENABLE_NETWORK 1
#define LL_PROFILER_CATEGORY_ENABLE_OCTREE 1
#define LL_PROFILER_CATEGORY_ENABLE_PIPELINE 1
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index b06fee0ec2..394212ee0d 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -26,20 +26,26 @@
#include "linden_common.h"
#include "llqueuedthread.h"
+#include
+
#include "llstl.h"
#include "lltimer.h" // ms_sleep()
-#include "lltracethreadrecorder.h"
+#include "llmutex.h"
//============================================================================
// MAIN THREAD
LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) :
- LLThread(name),
- mThreaded(threaded),
- mIdleThread(TRUE),
- mNextHandle(0),
- mStarted(FALSE)
+ LLThread(name),
+ mIdleThread(TRUE),
+ mNextHandle(0),
+ mStarted(FALSE),
+ mThreaded(threaded),
+ mRequestQueue(name, 1024 * 1024)
{
+ llassert(threaded); // not threaded implementation is deprecated
+ mMainQueue = LL::WorkQueue::getInstance("mainloop");
+
if (mThreaded)
{
if(should_pause)
@@ -69,6 +75,11 @@ void LLQueuedThread::shutdown()
unpause(); // MAIN THREAD
if (mThreaded)
{
+ if (mRequestQueue.size() == 0)
+ {
+ mRequestQueue.close();
+ }
+
S32 timeout = 100;
for ( ; timeout>0; timeout--)
{
@@ -104,6 +115,8 @@ void LLQueuedThread::shutdown()
{
LL_WARNS() << "~LLQueuedThread() called with active requests: " << active_count << LL_ENDL;
}
+
+ mRequestQueue.close();
}
//----------------------------------------------------------------------------
@@ -112,6 +125,7 @@ void LLQueuedThread::shutdown()
// virtual
size_t LLQueuedThread::update(F32 max_time_ms)
{
+ LL_PROFILE_ZONE_SCOPED;
if (!mStarted)
{
if (!mThreaded)
@@ -125,29 +139,34 @@ size_t LLQueuedThread::update(F32 max_time_ms)
size_t LLQueuedThread::updateQueue(F32 max_time_ms)
{
- F64 max_time = (F64)max_time_ms * .001;
- LLTimer timer;
- size_t pending = 1;
-
+ LL_PROFILE_ZONE_SCOPED;
// Frame Update
if (mThreaded)
{
- pending = getPending();
- if(pending > 0)
+ // schedule a call to threadedUpdate for every call to updateQueue
+ if (!isQuitting())
+ {
+ mRequestQueue.post([=]()
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qt - update");
+ mIdleThread = FALSE;
+ threadedUpdate();
+ mIdleThread = TRUE;
+ }
+ );
+ }
+
+ if(getPending() > 0)
{
- unpause();
- }
+ unpause();
+ }
}
else
{
- while (pending > 0)
- {
- pending = processNextRequest();
- if (max_time && timer.getElapsedTimeF64() > max_time)
- break;
- }
+ mRequestQueue.runFor(std::chrono::microseconds((int) (max_time_ms*1000.f)));
+ threadedUpdate();
}
- return pending;
+ return getPending();
}
void LLQueuedThread::incQueue()
@@ -166,11 +185,7 @@ void LLQueuedThread::incQueue()
// May be called from any thread
size_t LLQueuedThread::getPending()
{
- size_t res;
- lockData();
- res = mRequestQueue.size();
- unlockData();
- return res;
+ return mRequestQueue.size();
}
// MAIN thread
@@ -195,35 +210,28 @@ void LLQueuedThread::waitOnPending()
// MAIN thread
void LLQueuedThread::printQueueStats()
{
- lockData();
- if (!mRequestQueue.empty())
+ U32 size = mRequestQueue.size();
+ if (size > 0)
{
- QueuedRequest *req = *mRequestQueue.begin();
- LL_INFOS() << llformat("Pending Requests:%d Current status:%d", mRequestQueue.size(), req->getStatus()) << LL_ENDL;
+ LL_INFOS() << llformat("Pending Requests:%d ", mRequestQueue.size()) << LL_ENDL;
}
else
{
LL_INFOS() << "Queued Thread Idle" << LL_ENDL;
}
- unlockData();
}
// MAIN thread
LLQueuedThread::handle_t LLQueuedThread::generateHandle()
{
- lockData();
- while ((mNextHandle == nullHandle()) || (mRequestHash.find(mNextHandle)))
- {
- mNextHandle++;
- }
- const LLQueuedThread::handle_t res = mNextHandle++;
- unlockData();
+ U32 res = ++mNextHandle;
return res;
}
// MAIN thread
bool LLQueuedThread::addRequest(QueuedRequest* req)
{
+ LL_PROFILE_ZONE_SCOPED;
if (mStatus == QUITTING)
{
return false;
@@ -231,14 +239,14 @@ bool LLQueuedThread::addRequest(QueuedRequest* req)
lockData();
req->setStatus(STATUS_QUEUED);
- mRequestQueue.insert(req);
- mRequestHash.insert(req);
+ mRequestHash.insert(req);
#if _DEBUG
// LL_INFOS() << llformat("LLQueuedThread::Added req [%08d]",handle) << LL_ENDL;
#endif
unlockData();
- incQueue();
+ llassert(!mDataLock->isSelfLocked());
+ mRequestQueue.post([this, req]() { processRequest(req); });
return true;
}
@@ -246,6 +254,7 @@ bool LLQueuedThread::addRequest(QueuedRequest* req)
// MAIN thread
bool LLQueuedThread::waitForResult(LLQueuedThread::handle_t handle, bool auto_complete)
{
+ LL_PROFILE_ZONE_SCOPED;
llassert (handle != nullHandle());
bool res = false;
bool waspaused = isPaused();
@@ -312,6 +321,7 @@ LLQueuedThread::status_t LLQueuedThread::getRequestStatus(handle_t handle)
void LLQueuedThread::abortRequest(handle_t handle, bool autocomplete)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
lockData();
QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
if (req)
@@ -333,30 +343,9 @@ void LLQueuedThread::setFlags(handle_t handle, U32 flags)
unlockData();
}
-void LLQueuedThread::setPriority(handle_t handle, U32 priority)
-{
- lockData();
- QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
- if (req)
- {
- if(req->getStatus() == STATUS_INPROGRESS)
- {
- // not in list
- req->setPriority(priority);
- }
- else if(req->getStatus() == STATUS_QUEUED)
- {
- // remove from list then re-insert
- llverify(mRequestQueue.erase(req) == 1);
- req->setPriority(priority);
- mRequestQueue.insert(req);
- }
- }
- unlockData();
-}
-
bool LLQueuedThread::completeRequest(handle_t handle)
{
+ LL_PROFILE_ZONE_SCOPED;
bool res = false;
lockData();
QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
@@ -399,88 +388,120 @@ bool LLQueuedThread::check()
//============================================================================
// Runs on its OWN thread
-size_t LLQueuedThread::processNextRequest()
+void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req)
{
- QueuedRequest *req;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+
+ mIdleThread = FALSE;
+ //threadedUpdate();
+
// Get next request from pool
lockData();
- while(1)
+ if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
{
- req = NULL;
- if (mRequestQueue.empty())
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qtpr - abort");
+ req->setStatus(STATUS_ABORTED);
+ req->finishRequest(false);
+ if (req->getFlags() & FLAG_AUTO_COMPLETE)
{
- break;
- }
- req = *mRequestQueue.begin();
- mRequestQueue.erase(mRequestQueue.begin());
- if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
- {
- req->setStatus(STATUS_ABORTED);
- req->finishRequest(false);
- if (req->getFlags() & FLAG_AUTO_COMPLETE)
- {
- mRequestHash.erase(req);
- req->deleteRequest();
+ mRequestHash.erase(req);
+ req->deleteRequest();
// check();
- }
- continue;
}
- llassert_always(req->getStatus() == STATUS_QUEUED);
- break;
+ unlockData();
}
- U32 start_priority = 0 ;
- if (req)
- {
- req->setStatus(STATUS_INPROGRESS);
- start_priority = req->getPriority();
- }
- unlockData();
+ else
+ {
+ llassert_always(req->getStatus() == STATUS_QUEUED);
- // This is the only place we will call req->setStatus() after
- // it has initially been seet to STATUS_QUEUED, so it is
- // safe to access req.
- if (req)
- {
- // process request
- bool complete = req->processRequest();
+ if (req)
+ {
+ req->setStatus(STATUS_INPROGRESS);
+ }
+ unlockData();
- if (complete)
- {
- lockData();
- req->setStatus(STATUS_COMPLETE);
- req->finishRequest(true);
- if (req->getFlags() & FLAG_AUTO_COMPLETE)
- {
- mRequestHash.erase(req);
- req->deleteRequest();
-// check();
- }
- unlockData();
- }
- else
- {
- lockData();
- req->setStatus(STATUS_QUEUED);
- mRequestQueue.insert(req);
- unlockData();
- if (mThreaded && start_priority < PRIORITY_NORMAL)
- {
- ms_sleep(1); // sleep the thread a little
- }
- }
-
- LLTrace::get_thread_recorder()->pushToParent();
- }
+ // This is the only place we will call req->setStatus() after
+ // it has initially been seet to STATUS_QUEUED, so it is
+ // safe to access req.
+ if (req)
+ {
+ // process request
+ bool complete = req->processRequest();
- return getPending();
+ if (complete)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qtpr - complete");
+ lockData();
+ req->setStatus(STATUS_COMPLETE);
+ req->finishRequest(true);
+ if (req->getFlags() & FLAG_AUTO_COMPLETE)
+ {
+ mRequestHash.erase(req);
+ req->deleteRequest();
+ // check();
+ }
+ unlockData();
+ }
+ else
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qtpr - retry");
+ //put back on queue and try again in 0.1ms
+ lockData();
+ req->setStatus(STATUS_QUEUED);
+
+ unlockData();
+
+ llassert(!mDataLock->isSelfLocked());
+
+#if 0
+ // try again on next frame
+ // NOTE: tried using "post" with a time in the future, but this
+ // would invariably cause this thread to wait for a long time (10+ ms)
+ // while work is pending
+ bool ret = LL::WorkQueue::postMaybe(
+ mMainQueue,
+ [=]()
+ {
+ LL_PROFILE_ZONE_NAMED("processRequest - retry");
+ mRequestQueue.post([=]()
+ {
+ LL_PROFILE_ZONE_NAMED("processRequest - retry"); // <-- not redundant, track retry on both queues
+ processRequest(req);
+ });
+ });
+ llassert(ret);
+#else
+ using namespace std::chrono_literals;
+ auto retry_time = LL::WorkQueue::TimePoint::clock::now() + 16ms;
+ mRequestQueue.post([=]
+ {
+ LL_PROFILE_ZONE_NAMED("processRequest - retry");
+ if (LL::WorkQueue::TimePoint::clock::now() < retry_time)
+ {
+ auto sleep_time = std::chrono::duration_cast(retry_time - LL::WorkQueue::TimePoint::clock::now());
+
+ if (sleep_time.count() > 0)
+ {
+ ms_sleep(sleep_time.count());
+ }
+ }
+ processRequest(req);
+ });
+#endif
+
+ }
+ }
+ }
+
+ mIdleThread = TRUE;
}
// virtual
bool LLQueuedThread::runCondition()
{
// mRunCondition must be locked here
- if (mRequestQueue.empty() && mIdleThread)
+ if (mRequestQueue.size() == 0 && mIdleThread)
return false;
else
return true;
@@ -494,18 +515,13 @@ void LLQueuedThread::run()
startThread();
mStarted = TRUE;
- while (1)
+
+ /*while (1)
{
+ LL_PROFILE_ZONE_SCOPED;
// this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state.
checkPause();
- if (isQuitting())
- {
- LLTrace::get_thread_recorder()->pushToParent();
- endThread();
- break;
- }
-
mIdleThread = FALSE;
threadedUpdate();
@@ -514,12 +530,18 @@ void LLQueuedThread::run()
if (pending_work == 0)
{
+ //LL_PROFILE_ZONE_NAMED("LLQueuedThread - sleep");
mIdleThread = TRUE;
- ms_sleep(1);
+ //ms_sleep(1);
}
//LLThread::yield(); // thread should yield after each request
- }
+ }*/
+ mRequestQueue.runUntilClose();
+
+ endThread();
LL_INFOS() << "LLQueuedThread " << mName << " EXITING." << LL_ENDL;
+
+
}
// virtual
@@ -539,10 +561,9 @@ void LLQueuedThread::threadedUpdate()
//============================================================================
-LLQueuedThread::QueuedRequest::QueuedRequest(LLQueuedThread::handle_t handle, U32 priority, U32 flags) :
+LLQueuedThread::QueuedRequest::QueuedRequest(LLQueuedThread::handle_t handle, U32 flags) :
LLSimpleHashEntry(handle),
mStatus(STATUS_UNKNOWN),
- mPriority(priority),
mFlags(flags)
{
}
diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h
index 90fce3dc5d..814dbc4c38 100644
--- a/indra/llcommon/llqueuedthread.h
+++ b/indra/llcommon/llqueuedthread.h
@@ -36,6 +36,7 @@
#include "llthread.h"
#include "llsimplehash.h"
+#include "workqueue.h"
//============================================================================
// Note: ~LLQueuedThread is O(N) N=# of queued threads, assumed to be small
@@ -45,15 +46,6 @@ class LL_COMMON_API LLQueuedThread : public LLThread
{
//------------------------------------------------------------------------
public:
- enum priority_t {
- PRIORITY_IMMEDIATE = 0x7FFFFFFF,
- PRIORITY_URGENT = 0x40000000,
- PRIORITY_HIGH = 0x30000000,
- PRIORITY_NORMAL = 0x20000000,
- PRIORITY_LOW = 0x10000000,
- PRIORITY_LOWBITS = 0x0FFFFFFF,
- PRIORITY_HIGHBITS = 0x70000000
- };
enum status_t {
STATUS_EXPIRED = -1,
STATUS_UNKNOWN = 0,
@@ -82,28 +74,17 @@ public:
virtual ~QueuedRequest(); // use deleteRequest()
public:
- QueuedRequest(handle_t handle, U32 priority, U32 flags = 0);
+ QueuedRequest(handle_t handle, U32 flags = 0);
status_t getStatus()
{
return mStatus;
}
- U32 getPriority() const
- {
- return mPriority;
- }
U32 getFlags() const
{
return mFlags;
}
- bool higherPriority(const QueuedRequest& second) const
- {
- if ( mPriority == second.mPriority)
- return mHashKey < second.mHashKey;
- else
- return mPriority > second.mPriority;
- }
-
+
protected:
status_t setStatus(status_t newstatus)
{
@@ -121,28 +102,11 @@ public:
virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted
virtual void deleteRequest(); // Only method to delete a request
- void setPriority(U32 pri)
- {
- // Only do this on a request that is not in a queued list!
- mPriority = pri;
- };
-
protected:
LLAtomicBase mStatus;
- U32 mPriority;
U32 mFlags;
};
-protected:
- struct queued_request_less
- {
- bool operator()(const QueuedRequest* lhs, const QueuedRequest* rhs) const
- {
- return lhs->higherPriority(*rhs); // higher priority in front of queue (set)
- }
- };
-
-
//------------------------------------------------------------------------
public:
@@ -167,7 +131,7 @@ private:
protected:
handle_t generateHandle();
bool addRequest(QueuedRequest* req);
- size_t processNextRequest(void);
+ void processRequest(QueuedRequest* req);
void incQueue();
public:
@@ -186,7 +150,6 @@ public:
status_t getRequestStatus(handle_t handle);
void abortRequest(handle_t handle, bool autocomplete);
void setFlags(handle_t handle, U32 flags);
- void setPriority(handle_t handle, U32 priority);
bool completeRequest(handle_t handle);
// This is public for support classes like LLWorkerThread,
// but generally the methods above should be used.
@@ -200,8 +163,10 @@ protected:
BOOL mStarted; // required when mThreaded is false to call startThread() from update()
LLAtomicBool mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
- typedef std::set request_queue_t;
- request_queue_t mRequestQueue;
+ //typedef std::set request_queue_t;
+ //request_queue_t mRequestQueue;
+ LL::WorkQueue mRequestQueue;
+ LL::WorkQueue::weak_t mMainQueue;
enum { REQUEST_HASH_SIZE = 512 }; // must be power of 2
typedef LLSimpleHash request_hash_t;
diff --git a/indra/llcommon/llrand.cpp b/indra/llcommon/llrand.cpp
index cb28a8f5c3..33afc50cf7 100644
--- a/indra/llcommon/llrand.cpp
+++ b/indra/llcommon/llrand.cpp
@@ -58,46 +58,14 @@
* to restore uniform distribution.
*/
-// *NOTE: The system rand implementation is probably not correct.
-#define LL_USE_SYSTEM_RAND 0
-
-#if LL_USE_SYSTEM_RAND
-#include
-#endif
-
-#if LL_USE_SYSTEM_RAND
-class LLSeedRand
-{
-public:
- LLSeedRand()
- {
-#if LL_WINDOWS
- srand(LLUUID::getRandomSeed());
-#else
- srand48(LLUUID::getRandomSeed());
-#endif
- }
-};
-static LLSeedRand sRandomSeeder;
-inline F64 ll_internal_random_double()
-{
-#if LL_WINDOWS
- return (F64)rand() / (F64)RAND_MAX;
-#else
- return drand48();
-#endif
-}
-inline F32 ll_internal_random_float()
-{
-#if LL_WINDOWS
- return (F32)rand() / (F32)RAND_MAX;
-#else
- return (F32)drand48();
-#endif
-}
-#else
static LLRandLagFib2281 gRandomGenerator(LLUUID::getRandomSeed());
-inline F64 ll_internal_random_double()
+
+// no default implementation, only specific F64 and F32 specializations
+template
+inline REAL ll_internal_random();
+
+template <>
+inline F64 ll_internal_random()
{
// *HACK: Through experimentation, we have found that dual core
// CPUs (or at least multi-threaded processes) seem to
@@ -108,15 +76,35 @@ inline F64 ll_internal_random_double()
return rv;
}
+template <>
+inline F32 ll_internal_random()
+{
+ return F32(ll_internal_random());
+}
+
+/*------------------------------ F64 aliases -------------------------------*/
+inline F64 ll_internal_random_double()
+{
+ return ll_internal_random();
+}
+
+F64 ll_drand()
+{
+ return ll_internal_random_double();
+}
+
+/*------------------------------ F32 aliases -------------------------------*/
inline F32 ll_internal_random_float()
{
- // The clamping rules are described above.
- F32 rv = (F32)gRandomGenerator();
- if(!((rv >= 0.0f) && (rv < 1.0f))) return fmod(rv, 1.f);
- return rv;
+ return ll_internal_random();
}
-#endif
+F32 ll_frand()
+{
+ return ll_internal_random_float();
+}
+
+/*-------------------------- clamped random range --------------------------*/
S32 ll_rand()
{
return ll_rand(RAND_MAX);
@@ -130,42 +118,28 @@ S32 ll_rand(S32 val)
return rv;
}
-F32 ll_frand()
+template
+REAL ll_grand(REAL val)
{
- return ll_internal_random_float();
+ // The clamping rules are described above.
+ REAL rv = ll_internal_random() * val;
+ if(val > 0)
+ {
+ if(rv >= val) return REAL();
+ }
+ else
+ {
+ if(rv <= val) return REAL();
+ }
+ return rv;
}
F32 ll_frand(F32 val)
{
- // The clamping rules are described above.
- F32 rv = ll_internal_random_float() * val;
- if(val > 0)
- {
- if(rv >= val) return 0.0f;
- }
- else
- {
- if(rv <= val) return 0.0f;
- }
- return rv;
-}
-
-F64 ll_drand()
-{
- return ll_internal_random_double();
+ return ll_grand(val);
}
F64 ll_drand(F64 val)
{
- // The clamping rules are described above.
- F64 rv = ll_internal_random_double() * val;
- if(val > 0)
- {
- if(rv >= val) return 0.0;
- }
- else
- {
- if(rv <= val) return 0.0;
- }
- return rv;
+ return ll_grand(val);
}
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 3db456ddb3..a475be6293 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -475,6 +475,7 @@ LLSDNotationParser::~LLSDNotationParser()
// virtual
S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
// map: { string:object, string:object }
// array: [ object, object, object ]
// undef: !
@@ -734,6 +735,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) c
S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) const
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
// map: { string:object, string:object }
map = LLSD::emptyMap();
S32 parse_count = 0;
@@ -794,6 +796,7 @@ S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) c
S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
// array: [ object, object, object ]
array = LLSD::emptyArray();
S32 parse_count = 0;
@@ -833,6 +836,7 @@ S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array, S32 max_dept
bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
std::string value;
auto count = deserialize_string(istr, value, mMaxBytesLeft);
if(PARSE_FAILURE == count) return false;
@@ -843,6 +847,7 @@ bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
// binary: b##"ff3120ab1"
// or: b(len)"..."
@@ -945,6 +950,7 @@ LLSDBinaryParser::~LLSDBinaryParser()
// virtual
S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
/**
* Undefined: '!'
* Boolean: '1' for true '0' for false
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index ac128c9f86..38b11eb32b 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -923,6 +923,8 @@ void LLSDXMLParser::parsePart(const char *buf, llssize len)
// virtual
S32 LLSDXMLParser::doParse(std::istream& input, LLSD& data, S32 max_depth) const
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
+
#ifdef XML_PARSER_PERFORMANCE_TESTS
XML_Timer timer( &parseTime );
#endif // XML_PARSER_PERFORMANCE_TESTS
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 91cb65b815..938685bae6 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -771,20 +771,28 @@ static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB)
}
#endif
+#if LL_DARWIN
+// static
+U32Kilobytes LLMemoryInfo::getHardwareMemSize()
+{
+ // This might work on Linux as well. Someone check...
+ uint64_t phys = 0;
+ int mib[2] = { CTL_HW, HW_MEMSIZE };
+
+ size_t len = sizeof(phys);
+ sysctl(mib, 2, &phys, &len, NULL, 0);
+
+ return U64Bytes(phys);
+}
+#endif
+
U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
{
#if LL_WINDOWS
return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger()));
#elif LL_DARWIN
- // This might work on Linux as well. Someone check...
- uint64_t phys = 0;
- int mib[2] = { CTL_HW, HW_MEMSIZE };
-
- size_t len = sizeof(phys);
- sysctl(mib, 2, &phys, &len, NULL, 0);
-
- return U64Bytes(phys);
+ return getHardwareMemSize();
#elif LL_LINUX
U64 phys = 0;
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index 70a03810c5..08d4abffa2 100644
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -129,7 +129,10 @@ public:
LLMemoryInfo(); ///< Default constructor
void stream(std::ostream& s) const; ///< output text info to s
- U32Kilobytes getPhysicalMemoryKB() const;
+ U32Kilobytes getPhysicalMemoryKB() const;
+#if LL_DARWIN
+ static U32Kilobytes getHardwareMemSize(); // Because some Mac linkers won't let us reference extern gSysMemory from a different lib.
+#endif
//get the available memory infomation in KiloBytes.
static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb);
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index a807acc56e..4eaa05c335 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -42,6 +42,7 @@
#ifdef LL_WINDOWS
+
const DWORD MS_VC_EXCEPTION=0x406D1388;
#pragma pack(push,8)
@@ -133,6 +134,15 @@ void LLThread::threadRun()
{
#ifdef LL_WINDOWS
set_thread_name(-1, mName.c_str());
+
+#if 0 // probably a bad idea, see usage of SetThreadIdealProcessor in LLWindowWin32)
+ HANDLE hThread = GetCurrentThread();
+ if (hThread)
+ {
+ SetThreadAffinityMask(hThread, (DWORD_PTR) 0xFFFFFFFFFFFFFFFE);
+ }
+#endif
+
#endif
LL_PROFILER_SET_THREAD_NAME( mName.c_str() );
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 58bedacf43..1a99ac2886 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -30,6 +30,9 @@
#include "u64.h"
+#include
+#include
+
#if LL_WINDOWS
# include "llwin32headerslean.h"
#elif LL_LINUX || LL_DARWIN
@@ -62,9 +65,18 @@ LLTimer* LLTimer::sTimer = NULL;
//---------------------------------------------------------------------------
#if LL_WINDOWS
+
+
+#if 0
void ms_sleep(U32 ms)
{
- Sleep(ms);
+ LL_PROFILE_ZONE_SCOPED;
+ using TimePoint = std::chrono::steady_clock::time_point;
+ auto resume_time = TimePoint::clock::now() + std::chrono::milliseconds(ms);
+ while (TimePoint::clock::now() < resume_time)
+ {
+ std::this_thread::yield(); //note: don't use LLThread::yield here to avoid yielding for too long
+ }
}
U32 micro_sleep(U64 us, U32 max_yields)
@@ -74,6 +86,35 @@ U32 micro_sleep(U64 us, U32 max_yields)
ms_sleep((U32)(us / 1000));
return 0;
}
+
+#else
+
+U32 micro_sleep(U64 us, U32 max_yields)
+{
+ LL_PROFILE_ZONE_SCOPED
+#if 0
+ LARGE_INTEGER ft;
+ ft.QuadPart = -static_cast(us * 10); // '-' using relative time
+
+ HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL);
+ SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
+ WaitForSingleObject(timer, INFINITE);
+ CloseHandle(timer);
+#else
+ Sleep(us / 1000);
+#endif
+
+ return 0;
+}
+
+void ms_sleep(U32 ms)
+{
+ LL_PROFILE_ZONE_SCOPED
+ micro_sleep(ms * 1000, 0);
+}
+
+#endif
+
#elif LL_LINUX || LL_DARWIN
static void _sleep_loop(struct timespec& thiswait)
{
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index 5655e8e2f2..200add404f 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -1,31 +1,31 @@
-/**
+/**
* @file lluuid.cpp
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
-// We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.
+ // We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.
#if LL_WINDOWS
#include "llwin32headers.h"
// ugh, this is ugly. We need to straighten out our linking for this library
@@ -51,7 +51,7 @@ const LLUUID LLUUID::null;
const LLTransactionID LLTransactionID::tnull;
// static
-LLMutex * LLUUID::mMutex = NULL;
+LLMutex* LLUUID::mMutex = NULL;
@@ -60,15 +60,15 @@ LLMutex * LLUUID::mMutex = NULL;
NOT DONE YET!!!
static char BASE85_TABLE[] = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
- 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
- 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
- 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
- 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
- 'y', 'z', '!', '#', '$', '%', '&', '(', ')', '*',
- '+', '-', ';', '[', '=', '>', '?', '@', '^', '_',
- '`', '{', '|', '}', '~', '\0'
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+ 'y', 'z', '!', '#', '$', '%', '&', '(', ')', '*',
+ '+', '-', ';', '[', '=', '>', '?', '@', '^', '_',
+ '`', '{', '|', '}', '~', '\0'
};
@@ -94,28 +94,28 @@ return ret;
void LLUUID::toBase85(char* out)
{
- U32* me = (U32*)&(mData[0]);
- for(S32 i = 0; i < 4; ++i)
- {
- char* o = &out[i*i];
- for(S32 j = 0; j < 5; ++j)
- {
- o[4-j] = BASE85_TABLE[ me[i] % 85];
- word /= 85;
- }
- }
+ U32* me = (U32*)&(mData[0]);
+ for(S32 i = 0; i < 4; ++i)
+ {
+ char* o = &out[i*i];
+ for(S32 j = 0; j < 5; ++j)
+ {
+ o[4-j] = BASE85_TABLE[ me[i] % 85];
+ word /= 85;
+ }
+ }
}
unsigned int decode( char const * fiveChars ) throw( bad_input_data )
{
- unsigned int ret = 0;
- for( S32 ix = 0; ix < 5; ++ix )
- {
- char * s = strchr( encodeTable, fiveChars[ ix ] );
- ret = ret * 85 + (s-encodeTable);
- }
- return ret;
-}
+ unsigned int ret = 0;
+ for( S32 ix = 0; ix < 5; ++ix )
+ {
+ char * s = strchr( encodeTable, fiveChars[ ix ] );
+ ret = ret * 85 + (s-encodeTable);
+ }
+ return ret;
+}
*/
#define LL_USE_JANKY_RANDOM_NUMBER_GENERATOR 0
@@ -130,8 +130,8 @@ static U64 sJankyRandomSeed(LLUUID::getRandomSeed());
*/
U32 janky_fast_random_bytes()
{
- sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223);
- return (U32)sJankyRandomSeed;
+ sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223);
+ return (U32)sJankyRandomSeed;
}
/**
@@ -139,8 +139,8 @@ U32 janky_fast_random_bytes()
*/
U32 janky_fast_random_byes_range(U32 val)
{
- sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223);
- return (U32)(sJankyRandomSeed) % val;
+ sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223);
+ return (U32)(sJankyRandomSeed) % val;
}
/**
@@ -148,257 +148,257 @@ U32 janky_fast_random_byes_range(U32 val)
*/
U32 janky_fast_random_seeded_bytes(U32 seed, U32 val)
{
- seed = U64L(1664525) * (U64)(seed) + U64L(1013904223);
- return (U32)(seed) % val;
+ seed = U64L(1664525) * (U64)(seed)+U64L(1013904223);
+ return (U32)(seed) % val;
}
#endif
// Common to all UUID implementations
void LLUUID::toString(std::string& out) const
{
- out = llformat(
- "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- (U8)(mData[0]),
- (U8)(mData[1]),
- (U8)(mData[2]),
- (U8)(mData[3]),
- (U8)(mData[4]),
- (U8)(mData[5]),
- (U8)(mData[6]),
- (U8)(mData[7]),
- (U8)(mData[8]),
- (U8)(mData[9]),
- (U8)(mData[10]),
- (U8)(mData[11]),
- (U8)(mData[12]),
- (U8)(mData[13]),
- (U8)(mData[14]),
- (U8)(mData[15]));
+ out = llformat(
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (U8)(mData[0]),
+ (U8)(mData[1]),
+ (U8)(mData[2]),
+ (U8)(mData[3]),
+ (U8)(mData[4]),
+ (U8)(mData[5]),
+ (U8)(mData[6]),
+ (U8)(mData[7]),
+ (U8)(mData[8]),
+ (U8)(mData[9]),
+ (U8)(mData[10]),
+ (U8)(mData[11]),
+ (U8)(mData[12]),
+ (U8)(mData[13]),
+ (U8)(mData[14]),
+ (U8)(mData[15]));
}
// *TODO: deprecate
-void LLUUID::toString(char *out) const
+void LLUUID::toString(char* out) const
{
- std::string buffer;
- toString(buffer);
- strcpy(out,buffer.c_str()); /* Flawfinder: ignore */
+ std::string buffer;
+ toString(buffer);
+ strcpy(out, buffer.c_str()); /* Flawfinder: ignore */
}
void LLUUID::toCompressedString(std::string& out) const
{
- char bytes[UUID_BYTES+1];
- memcpy(bytes, mData, UUID_BYTES); /* Flawfinder: ignore */
- bytes[UUID_BYTES] = '\0';
- out.assign(bytes, UUID_BYTES);
+ char bytes[UUID_BYTES + 1];
+ memcpy(bytes, mData, UUID_BYTES); /* Flawfinder: ignore */
+ bytes[UUID_BYTES] = '\0';
+ out.assign(bytes, UUID_BYTES);
}
// *TODO: deprecate
-void LLUUID::toCompressedString(char *out) const
+void LLUUID::toCompressedString(char* out) const
{
- memcpy(out, mData, UUID_BYTES); /* Flawfinder: ignore */
- out[UUID_BYTES] = '\0';
+ memcpy(out, mData, UUID_BYTES); /* Flawfinder: ignore */
+ out[UUID_BYTES] = '\0';
}
std::string LLUUID::getString() const
{
- return asString();
+ return asString();
}
std::string LLUUID::asString() const
{
- std::string str;
- toString(str);
- return str;
+ std::string str;
+ toString(str);
+ return str;
}
BOOL LLUUID::set(const char* in_string, BOOL emit)
{
- return set(ll_safe_string(in_string),emit);
+ return set(ll_safe_string(in_string), emit);
}
BOOL LLUUID::set(const std::string& in_string, BOOL emit)
{
- BOOL broken_format = FALSE;
+ BOOL broken_format = FALSE;
- // empty strings should make NULL uuid
- if (in_string.empty())
- {
- setNull();
- return TRUE;
- }
+ // empty strings should make NULL uuid
+ if (in_string.empty())
+ {
+ setNull();
+ return TRUE;
+ }
- if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */
- {
- // I'm a moron. First implementation didn't have the right UUID format.
- // Shouldn't see any of these any more
- if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */
- {
- if(emit)
- {
- LL_WARNS() << "Warning! Using broken UUID string format" << LL_ENDL;
- }
- broken_format = TRUE;
- }
- else
- {
- // Bad UUID string. Spam as INFO, as most cases we don't care.
- if(emit)
- {
- //don't spam the logs because a resident can't spell.
- LL_WARNS() << "Bad UUID string: " << in_string << LL_ENDL;
- }
- setNull();
- return FALSE;
- }
- }
+ if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */
+ {
+ // I'm a moron. First implementation didn't have the right UUID format.
+ // Shouldn't see any of these any more
+ if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */
+ {
+ if (emit)
+ {
+ LL_WARNS() << "Warning! Using broken UUID string format" << LL_ENDL;
+ }
+ broken_format = TRUE;
+ }
+ else
+ {
+ // Bad UUID string. Spam as INFO, as most cases we don't care.
+ if (emit)
+ {
+ //don't spam the logs because a resident can't spell.
+ LL_WARNS() << "Bad UUID string: " << in_string << LL_ENDL;
+ }
+ setNull();
+ return FALSE;
+ }
+ }
- U8 cur_pos = 0;
- S32 i;
- for (i = 0; i < UUID_BYTES; i++)
- {
- if ((i == 4) || (i == 6) || (i == 8) || (i == 10))
- {
- cur_pos++;
- if (broken_format && (i==10))
- {
- // Missing - in the broken format
- cur_pos--;
- }
- }
+ U8 cur_pos = 0;
+ S32 i;
+ for (i = 0; i < UUID_BYTES; i++)
+ {
+ if ((i == 4) || (i == 6) || (i == 8) || (i == 10))
+ {
+ cur_pos++;
+ if (broken_format && (i == 10))
+ {
+ // Missing - in the broken format
+ cur_pos--;
+ }
+ }
- mData[i] = 0;
+ mData[i] = 0;
- if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9'))
- {
- mData[i] += (U8)(in_string[cur_pos] - '0');
- }
- else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f'))
- {
- mData[i] += (U8)(10 + in_string[cur_pos] - 'a');
- }
- else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F'))
- {
- mData[i] += (U8)(10 + in_string[cur_pos] - 'A');
- }
- else
- {
- if(emit)
- {
- LL_WARNS() << "Invalid UUID string character" << LL_ENDL;
- }
- setNull();
- return FALSE;
- }
+ if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9'))
+ {
+ mData[i] += (U8)(in_string[cur_pos] - '0');
+ }
+ else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <= 'f'))
+ {
+ mData[i] += (U8)(10 + in_string[cur_pos] - 'a');
+ }
+ else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <= 'F'))
+ {
+ mData[i] += (U8)(10 + in_string[cur_pos] - 'A');
+ }
+ else
+ {
+ if (emit)
+ {
+ LL_WARNS() << "Invalid UUID string character" << LL_ENDL;
+ }
+ setNull();
+ return FALSE;
+ }
- mData[i] = mData[i] << 4;
- cur_pos++;
+ mData[i] = mData[i] << 4;
+ cur_pos++;
- if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9'))
- {
- mData[i] += (U8)(in_string[cur_pos] - '0');
- }
- else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f'))
- {
- mData[i] += (U8)(10 + in_string[cur_pos] - 'a');
- }
- else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F'))
- {
- mData[i] += (U8)(10 + in_string[cur_pos] - 'A');
- }
- else
- {
- if(emit)
- {
- LL_WARNS() << "Invalid UUID string character" << LL_ENDL;
- }
- setNull();
- return FALSE;
- }
- cur_pos++;
- }
+ if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9'))
+ {
+ mData[i] += (U8)(in_string[cur_pos] - '0');
+ }
+ else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <= 'f'))
+ {
+ mData[i] += (U8)(10 + in_string[cur_pos] - 'a');
+ }
+ else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <= 'F'))
+ {
+ mData[i] += (U8)(10 + in_string[cur_pos] - 'A');
+ }
+ else
+ {
+ if (emit)
+ {
+ LL_WARNS() << "Invalid UUID string character" << LL_ENDL;
+ }
+ setNull();
+ return FALSE;
+ }
+ cur_pos++;
+ }
- return TRUE;
+ return TRUE;
}
BOOL LLUUID::validate(const std::string& in_string)
{
- BOOL broken_format = FALSE;
- if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */
- {
- // I'm a moron. First implementation didn't have the right UUID format.
- if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */
- {
- broken_format = TRUE;
- }
- else
- {
- return FALSE;
- }
- }
+ BOOL broken_format = FALSE;
+ if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */
+ {
+ // I'm a moron. First implementation didn't have the right UUID format.
+ if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */
+ {
+ broken_format = TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
- U8 cur_pos = 0;
- for (U32 i = 0; i < 16; i++)
- {
- if ((i == 4) || (i == 6) || (i == 8) || (i == 10))
- {
- cur_pos++;
- if (broken_format && (i==10))
- {
- // Missing - in the broken format
- cur_pos--;
- }
- }
+ U8 cur_pos = 0;
+ for (U32 i = 0; i < 16; i++)
+ {
+ if ((i == 4) || (i == 6) || (i == 8) || (i == 10))
+ {
+ cur_pos++;
+ if (broken_format && (i == 10))
+ {
+ // Missing - in the broken format
+ cur_pos--;
+ }
+ }
- if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9'))
- {
- }
- else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f'))
- {
- }
- else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F'))
- {
- }
- else
- {
- return FALSE;
- }
+ if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9'))
+ {
+ }
+ else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <= 'f'))
+ {
+ }
+ else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <= 'F'))
+ {
+ }
+ else
+ {
+ return FALSE;
+ }
- cur_pos++;
+ cur_pos++;
- if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9'))
- {
- }
- else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f'))
- {
- }
- else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F'))
- {
- }
- else
- {
- return FALSE;
- }
- cur_pos++;
- }
- return TRUE;
+ if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9'))
+ {
+ }
+ else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <= 'f'))
+ {
+ }
+ else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <= 'F'))
+ {
+ }
+ else
+ {
+ return FALSE;
+ }
+ cur_pos++;
+ }
+ return TRUE;
}
const LLUUID& LLUUID::operator^=(const LLUUID& rhs)
{
- U32* me = (U32*)&(mData[0]);
- const U32* other = (U32*)&(rhs.mData[0]);
- for(S32 i = 0; i < 4; ++i)
- {
- me[i] = me[i] ^ other[i];
- }
- return *this;
+ U32* me = (U32*)&(mData[0]);
+ const U32* other = (U32*)&(rhs.mData[0]);
+ for (S32 i = 0; i < 4; ++i)
+ {
+ me[i] = me[i] ^ other[i];
+ }
+ return *this;
}
LLUUID LLUUID::operator^(const LLUUID& rhs) const
{
- LLUUID id(*this);
- id ^= rhs;
- return id;
+ LLUUID id(*this);
+ id ^= rhs;
+ return id;
}
// WARNING: this algorithm SHALL NOT be changed. It is also used by the server
@@ -406,107 +406,107 @@ LLUUID LLUUID::operator^(const LLUUID& rhs) const
// it would cause invalid assets.
void LLUUID::combine(const LLUUID& other, LLUUID& result) const
{
- LLMD5 md5_uuid;
- md5_uuid.update((unsigned char*)mData, 16);
- md5_uuid.update((unsigned char*)other.mData, 16);
- md5_uuid.finalize();
- md5_uuid.raw_digest(result.mData);
+ LLMD5 md5_uuid;
+ md5_uuid.update((unsigned char*)mData, 16);
+ md5_uuid.update((unsigned char*)other.mData, 16);
+ md5_uuid.finalize();
+ md5_uuid.raw_digest(result.mData);
}
-LLUUID LLUUID::combine(const LLUUID &other) const
+LLUUID LLUUID::combine(const LLUUID& other) const
{
- LLUUID combination;
- combine(other, combination);
- return combination;
+ LLUUID combination;
+ combine(other, combination);
+ return combination;
}
-std::ostream& operator<<(std::ostream& s, const LLUUID &uuid)
+std::ostream& operator<<(std::ostream& s, const LLUUID& uuid)
{
- std::string uuid_str;
- uuid.toString(uuid_str);
- s << uuid_str;
- return s;
+ std::string uuid_str;
+ uuid.toString(uuid_str);
+ s << uuid_str;
+ return s;
}
-std::istream& operator>>(std::istream &s, LLUUID &uuid)
+std::istream& operator>>(std::istream& s, LLUUID& uuid)
{
- U32 i;
- char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */
- for (i = 0; i < UUID_STR_LENGTH-1; i++)
- {
- s >> uuid_str[i];
- }
- uuid_str[i] = '\0';
- uuid.set(std::string(uuid_str));
- return s;
+ U32 i;
+ char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */
+ for (i = 0; i < UUID_STR_LENGTH - 1; i++)
+ {
+ s >> uuid_str[i];
+ }
+ uuid_str[i] = '\0';
+ uuid.set(std::string(uuid_str));
+ return s;
}
-static void get_random_bytes(void *buf, int nbytes)
+static void get_random_bytes(void* buf, int nbytes)
{
- int i;
- char *cp = (char *) buf;
+ int i;
+ char* cp = (char*)buf;
- // *NOTE: If we are not using the janky generator ll_rand()
- // generates at least 3 good bytes of data since it is 0 to
- // RAND_MAX. This could be made more efficient by copying all the
- // bytes.
- for (i=0; i < nbytes; i++)
+ // *NOTE: If we are not using the janky generator ll_rand()
+ // generates at least 3 good bytes of data since it is 0 to
+ // RAND_MAX. This could be made more efficient by copying all the
+ // bytes.
+ for (i = 0; i < nbytes; i++)
#if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
- *cp++ = janky_fast_random_bytes() & 0xFF;
+ * cp++ = janky_fast_random_bytes() & 0xFF;
#else
- *cp++ = ll_rand() & 0xFF;
+ * cp++ = ll_rand() & 0xFF;
#endif
- return;
+ return;
}
#if LL_WINDOWS
typedef struct _ASTAT_
{
- ADAPTER_STATUS adapt;
- NAME_BUFFER NameBuff [30];
+ ADAPTER_STATUS adapt;
+ NAME_BUFFER NameBuff[30];
}ASTAT, * PASTAT;
// static
-S32 LLUUID::getNodeID(unsigned char *node_id)
+S32 LLUUID::getNodeID(unsigned char* node_id)
{
- ASTAT Adapter;
- NCB Ncb;
- UCHAR uRetCode;
- LANA_ENUM lenum;
- int i;
- int retval = 0;
+ ASTAT Adapter;
+ NCB Ncb;
+ UCHAR uRetCode;
+ LANA_ENUM lenum;
+ int i;
+ int retval = 0;
- memset( &Ncb, 0, sizeof(Ncb) );
- Ncb.ncb_command = NCBENUM;
- Ncb.ncb_buffer = (UCHAR *)&lenum;
- Ncb.ncb_length = sizeof(lenum);
- uRetCode = Netbios( &Ncb );
+ memset(&Ncb, 0, sizeof(Ncb));
+ Ncb.ncb_command = NCBENUM;
+ Ncb.ncb_buffer = (UCHAR*)&lenum;
+ Ncb.ncb_length = sizeof(lenum);
+ uRetCode = Netbios(&Ncb);
- for(i=0; i < lenum.length ;i++)
- {
- memset( &Ncb, 0, sizeof(Ncb) );
- Ncb.ncb_command = NCBRESET;
- Ncb.ncb_lana_num = lenum.lana[i];
+ for (i = 0; i < lenum.length; i++)
+ {
+ memset(&Ncb, 0, sizeof(Ncb));
+ Ncb.ncb_command = NCBRESET;
+ Ncb.ncb_lana_num = lenum.lana[i];
- uRetCode = Netbios( &Ncb );
+ uRetCode = Netbios(&Ncb);
- memset( &Ncb, 0, sizeof (Ncb) );
- Ncb.ncb_command = NCBASTAT;
- Ncb.ncb_lana_num = lenum.lana[i];
+ memset(&Ncb, 0, sizeof(Ncb));
+ Ncb.ncb_command = NCBASTAT;
+ Ncb.ncb_lana_num = lenum.lana[i];
- strcpy( (char *)Ncb.ncb_callname, "* " ); /* Flawfinder: ignore */
- Ncb.ncb_buffer = (unsigned char *)&Adapter;
- Ncb.ncb_length = sizeof(Adapter);
+ strcpy((char*)Ncb.ncb_callname, "* "); /* Flawfinder: ignore */
+ Ncb.ncb_buffer = (unsigned char*)&Adapter;
+ Ncb.ncb_length = sizeof(Adapter);
- uRetCode = Netbios( &Ncb );
- if ( uRetCode == 0 )
- {
- memcpy(node_id,Adapter.adapt.adapter_address,6); /* Flawfinder: ignore */
- retval = 1;
- }
- }
- return retval;
+ uRetCode = Netbios(&Ncb);
+ if (uRetCode == 0)
+ {
+ memcpy(node_id, Adapter.adapt.adapter_address, 6); /* Flawfinder: ignore */
+ retval = 1;
+ }
+ }
+ return retval;
}
#elif LL_DARWIN
@@ -525,66 +525,66 @@ S32 LLUUID::getNodeID(unsigned char *node_id)
#include
#include
-// static
-S32 LLUUID::getNodeID(unsigned char *node_id)
+ // static
+S32 LLUUID::getNodeID(unsigned char* node_id)
{
- int i;
- unsigned char *a = NULL;
- struct ifaddrs *ifap, *ifa;
- int rv;
- S32 result = 0;
+ int i;
+ unsigned char* a = NULL;
+ struct ifaddrs* ifap, * ifa;
+ int rv;
+ S32 result = 0;
- if ((rv=getifaddrs(&ifap))==-1)
- {
- return -1;
- }
- if (ifap == NULL)
- {
- return -1;
- }
+ if ((rv = getifaddrs(&ifap)) == -1)
+ {
+ return -1;
+ }
+ if (ifap == NULL)
+ {
+ return -1;
+ }
- for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
- {
-// printf("Interface %s, address family %d, ", ifa->ifa_name, ifa->ifa_addr->sa_family);
- for(i=0; i< ifa->ifa_addr->sa_len; i++)
- {
-// printf("%02X ", (unsigned char)ifa->ifa_addr->sa_data[i]);
- }
-// printf("\n");
-
- if(ifa->ifa_addr->sa_family == AF_LINK)
- {
- // This is a link-level address
- struct sockaddr_dl *lla = (struct sockaddr_dl *)ifa->ifa_addr;
-
-// printf("\tLink level address, type %02X\n", lla->sdl_type);
+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
+ {
+ // printf("Interface %s, address family %d, ", ifa->ifa_name, ifa->ifa_addr->sa_family);
+ for (i = 0; i < ifa->ifa_addr->sa_len; i++)
+ {
+ // printf("%02X ", (unsigned char)ifa->ifa_addr->sa_data[i]);
+ }
+ // printf("\n");
- if(lla->sdl_type == IFT_ETHER)
- {
- // Use the first ethernet MAC in the list.
- // For some reason, the macro LLADDR() defined in net/if_dl.h doesn't expand correctly. This is what it would do.
- a = (unsigned char *)&((lla)->sdl_data);
- a += (lla)->sdl_nlen;
-
- if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
- {
- continue;
- }
+ if (ifa->ifa_addr->sa_family == AF_LINK)
+ {
+ // This is a link-level address
+ struct sockaddr_dl* lla = (struct sockaddr_dl*)ifa->ifa_addr;
- if (node_id)
- {
- memcpy(node_id, a, 6);
- result = 1;
- }
-
- // We found one.
- break;
- }
- }
- }
- freeifaddrs(ifap);
+ // printf("\tLink level address, type %02X\n", lla->sdl_type);
- return result;
+ if (lla->sdl_type == IFT_ETHER)
+ {
+ // Use the first ethernet MAC in the list.
+ // For some reason, the macro LLADDR() defined in net/if_dl.h doesn't expand correctly. This is what it would do.
+ a = (unsigned char*)&((lla)->sdl_data);
+ a += (lla)->sdl_nlen;
+
+ if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
+ {
+ continue;
+ }
+
+ if (node_id)
+ {
+ memcpy(node_id, a, 6);
+ result = 1;
+ }
+
+ // We found one.
+ break;
+ }
+ }
+ }
+ freeifaddrs(ifap);
+
+ return result;
}
#else
@@ -611,22 +611,22 @@ S32 LLUUID::getNodeID(unsigned char *node_id)
#endif
#endif
-// static
-S32 LLUUID::getNodeID(unsigned char *node_id)
+ // static
+S32 LLUUID::getNodeID(unsigned char* node_id)
{
- int sd;
- struct ifreq ifr, *ifrp;
- struct ifconf ifc;
- char buf[1024];
- int n, i;
- unsigned char *a;
-
-/*
- * BSD 4.4 defines the size of an ifreq to be
- * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
- * However, under earlier systems, sa_len isn't present, so the size is
- * just sizeof(struct ifreq)
- */
+ int sd;
+ struct ifreq ifr, * ifrp;
+ struct ifconf ifc;
+ char buf[1024];
+ int n, i;
+ unsigned char* a;
+
+ /*
+ * BSD 4.4 defines the size of an ifreq to be
+ * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
+ * However, under earlier systems, sa_len isn't present, so the size is
+ * just sizeof(struct ifreq)
+ */
#ifdef HAVE_SA_LEN
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
@@ -637,252 +637,253 @@ S32 LLUUID::getNodeID(unsigned char *node_id)
#define ifreq_size(i) sizeof(struct ifreq)
#endif /* HAVE_SA_LEN*/
- sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- if (sd < 0) {
- return -1;
- }
- memset(buf, 0, sizeof(buf));
- ifc.ifc_len = sizeof(buf);
- ifc.ifc_buf = buf;
- if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
- close(sd);
- return -1;
- }
- n = ifc.ifc_len;
- for (i = 0; i < n; i+= ifreq_size(*ifr) ) {
- ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
- strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); /* Flawfinder: ignore */
+ sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if (sd < 0) {
+ return -1;
+ }
+ memset(buf, 0, sizeof(buf));
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_buf = buf;
+ if (ioctl(sd, SIOCGIFCONF, (char*)&ifc) < 0) {
+ close(sd);
+ return -1;
+ }
+ n = ifc.ifc_len;
+ for (i = 0; i < n; i += ifreq_size(*ifr)) {
+ ifrp = (struct ifreq*)((char*)ifc.ifc_buf + i);
+ strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); /* Flawfinder: ignore */
#ifdef SIOCGIFHWADDR
- if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
- continue;
- a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
+ if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
+ continue;
+ a = (unsigned char*)&ifr.ifr_hwaddr.sa_data;
#else
#ifdef SIOCGENADDR
- if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
- continue;
- a = (unsigned char *) ifr.ifr_enaddr;
+ if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
+ continue;
+ a = (unsigned char*)ifr.ifr_enaddr;
#else
- /*
- * XXX we don't have a way of getting the hardware
- * address
- */
- close(sd);
- return 0;
+ /*
+ * XXX we don't have a way of getting the hardware
+ * address
+ */
+ close(sd);
+ return 0;
#endif /* SIOCGENADDR */
#endif /* SIOCGIFHWADDR */
- if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
- continue;
- if (node_id) {
- memcpy(node_id, a, 6); /* Flawfinder: ignore */
- close(sd);
- return 1;
- }
- }
- close(sd);
- return 0;
+ if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
+ continue;
+ if (node_id) {
+ memcpy(node_id, a, 6); /* Flawfinder: ignore */
+ close(sd);
+ return 1;
+ }
+ }
+ close(sd);
+ return 0;
}
#endif
-S32 LLUUID::cmpTime(uuid_time_t *t1, uuid_time_t *t2)
+S32 LLUUID::cmpTime(uuid_time_t* t1, uuid_time_t* t2)
{
- // Compare two time values.
+ // Compare two time values.
- if (t1->high < t2->high) return -1;
- if (t1->high > t2->high) return 1;
- if (t1->low < t2->low) return -1;
- if (t1->low > t2->low) return 1;
- return 0;
+ if (t1->high < t2->high) return -1;
+ if (t1->high > t2->high) return 1;
+ if (t1->low < t2->low) return -1;
+ if (t1->low > t2->low) return 1;
+ return 0;
}
-void LLUUID::getSystemTime(uuid_time_t *timestamp)
+void LLUUID::getSystemTime(uuid_time_t* timestamp)
{
- // Get system time with 100ns precision. Time is since Oct 15, 1582.
+ // Get system time with 100ns precision. Time is since Oct 15, 1582.
#if LL_WINDOWS
- ULARGE_INTEGER time;
- GetSystemTimeAsFileTime((FILETIME *)&time);
- // NT keeps time in FILETIME format which is 100ns ticks since
- // Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582.
- // The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec)
- // + 18 years and 5 leap days.
- time.QuadPart +=
- (unsigned __int64) (1000*1000*10) // seconds
- * (unsigned __int64) (60 * 60 * 24) // days
- * (unsigned __int64) (17+30+31+365*18+5); // # of days
+ ULARGE_INTEGER time;
+ GetSystemTimeAsFileTime((FILETIME*)&time);
+ // NT keeps time in FILETIME format which is 100ns ticks since
+ // Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582.
+ // The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec)
+ // + 18 years and 5 leap days.
+ time.QuadPart +=
+ (unsigned __int64)(1000 * 1000 * 10) // seconds
+ * (unsigned __int64)(60 * 60 * 24) // days
+ * (unsigned __int64)(17 + 30 + 31 + 365 * 18 + 5); // # of days
- timestamp->high = time.HighPart;
- timestamp->low = time.LowPart;
+ timestamp->high = time.HighPart;
+ timestamp->low = time.LowPart;
#else
- struct timeval tp;
- gettimeofday(&tp, 0);
+ struct timeval tp;
+ gettimeofday(&tp, 0);
- // Offset between UUID formatted times and Unix formatted times.
- // UUID UTC base time is October 15, 1582.
- // Unix base time is January 1, 1970.
- U64 uuid_time = ((U64)tp.tv_sec * 10000000) + (tp.tv_usec * 10) +
- U64L(0x01B21DD213814000);
- timestamp->high = (U32) (uuid_time >> 32);
- timestamp->low = (U32) (uuid_time & 0xFFFFFFFF);
+ // Offset between UUID formatted times and Unix formatted times.
+ // UUID UTC base time is October 15, 1582.
+ // Unix base time is January 1, 1970.
+ U64 uuid_time = ((U64)tp.tv_sec * 10000000) + (tp.tv_usec * 10) +
+ U64L(0x01B21DD213814000);
+ timestamp->high = (U32)(uuid_time >> 32);
+ timestamp->low = (U32)(uuid_time & 0xFFFFFFFF);
#endif
}
-void LLUUID::getCurrentTime(uuid_time_t *timestamp)
+void LLUUID::getCurrentTime(uuid_time_t* timestamp)
{
- // Get current time as 60 bit 100ns ticks since whenever.
- // Compensate for the fact that real clock resolution is less
- // than 100ns.
+ // Get current time as 60 bit 100ns ticks since whenever.
+ // Compensate for the fact that real clock resolution is less
+ // than 100ns.
- const U32 uuids_per_tick = 1024;
+ const U32 uuids_per_tick = 1024;
- static uuid_time_t time_last;
- static U32 uuids_this_tick;
- static BOOL init = FALSE;
+ static uuid_time_t time_last;
+ static U32 uuids_this_tick;
+ static BOOL init = FALSE;
- if (!init) {
- getSystemTime(&time_last);
- uuids_this_tick = uuids_per_tick;
- init = TRUE;
- mMutex = new LLMutex();
- }
+ if (!init) {
+ getSystemTime(&time_last);
+ uuids_this_tick = uuids_per_tick;
+ init = TRUE;
+ mMutex = new LLMutex();
+ }
- uuid_time_t time_now = {0,0};
+ uuid_time_t time_now = { 0,0 };
- while (1) {
- getSystemTime(&time_now);
+ while (1) {
+ getSystemTime(&time_now);
- // if clock reading changed since last UUID generated
- if (cmpTime(&time_last, &time_now)) {
- // reset count of uuid's generated with this clock reading
- uuids_this_tick = 0;
- break;
- }
- if (uuids_this_tick < uuids_per_tick) {
- uuids_this_tick++;
- break;
- }
- // going too fast for our clock; spin
- }
+ // if clock reading changed since last UUID generated
+ if (cmpTime(&time_last, &time_now)) {
+ // reset count of uuid's generated with this clock reading
+ uuids_this_tick = 0;
+ break;
+ }
+ if (uuids_this_tick < uuids_per_tick) {
+ uuids_this_tick++;
+ break;
+ }
+ // going too fast for our clock; spin
+ }
- time_last = time_now;
+ time_last = time_now;
- if (uuids_this_tick != 0) {
- if (time_now.low & 0x80000000) {
- time_now.low += uuids_this_tick;
- if (!(time_now.low & 0x80000000))
- time_now.high++;
- } else
- time_now.low += uuids_this_tick;
- }
+ if (uuids_this_tick != 0) {
+ if (time_now.low & 0x80000000) {
+ time_now.low += uuids_this_tick;
+ if (!(time_now.low & 0x80000000))
+ time_now.high++;
+ }
+ else
+ time_now.low += uuids_this_tick;
+ }
- timestamp->high = time_now.high;
- timestamp->low = time_now.low;
+ timestamp->high = time_now.high;
+ timestamp->low = time_now.low;
}
void LLUUID::generate()
{
- // Create a UUID.
- uuid_time_t timestamp;
+ // Create a UUID.
+ uuid_time_t timestamp;
- static unsigned char node_id[6]; /* Flawfinder: ignore */
- static int has_init = 0;
-
- // Create a UUID.
- static uuid_time_t time_last = {0,0};
- static U16 clock_seq = 0;
+ static unsigned char node_id[6]; /* Flawfinder: ignore */
+ static int has_init = 0;
+
+ // Create a UUID.
+ static uuid_time_t time_last = { 0,0 };
+ static U16 clock_seq = 0;
#if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
- static U32 seed = 0L; // dummy seed. reset it below
+ static U32 seed = 0L; // dummy seed. reset it below
#endif
- if (!has_init)
- {
- has_init = 1;
- if (getNodeID(node_id) <= 0)
- {
- get_random_bytes(node_id, 6);
- /*
- * Set multicast bit, to prevent conflicts
- * with IEEE 802 addresses obtained from
- * network cards
- */
- node_id[0] |= 0x80;
- }
+ if (!has_init)
+ {
+ has_init = 1;
+ if (getNodeID(node_id) <= 0)
+ {
+ get_random_bytes(node_id, 6);
+ /*
+ * Set multicast bit, to prevent conflicts
+ * with IEEE 802 addresses obtained from
+ * network cards
+ */
+ node_id[0] |= 0x80;
+ }
- getCurrentTime(&time_last);
+ getCurrentTime(&time_last);
#if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
- seed = time_last.low;
+ seed = time_last.low;
#endif
#if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
- clock_seq = (U16)janky_fast_random_seeded_bytes(seed, 65536);
+ clock_seq = (U16)janky_fast_random_seeded_bytes(seed, 65536);
#else
- clock_seq = (U16)ll_rand(65536);
+ clock_seq = (U16)ll_rand(65536);
#endif
- }
+ }
- // get current time
- getCurrentTime(×tamp);
- U16 our_clock_seq = clock_seq;
+ // get current time
+ getCurrentTime(×tamp);
+ U16 our_clock_seq = clock_seq;
- // if clock hasn't changed or went backward, change clockseq
- if (cmpTime(×tamp, &time_last) != 1)
- {
- LLMutexLock lock(mMutex);
- clock_seq = (clock_seq + 1) & 0x3FFF;
- if (clock_seq == 0)
- clock_seq++;
- our_clock_seq = clock_seq; // Ensure we're using a different clock_seq value from previous time
- }
+ // if clock hasn't changed or went backward, change clockseq
+ if (cmpTime(×tamp, &time_last) != 1)
+ {
+ LLMutexLock lock(mMutex);
+ clock_seq = (clock_seq + 1) & 0x3FFF;
+ if (clock_seq == 0)
+ clock_seq++;
+ our_clock_seq = clock_seq; // Ensure we're using a different clock_seq value from previous time
+ }
time_last = timestamp;
- memcpy(mData+10, node_id, 6); /* Flawfinder: ignore */
- U32 tmp;
- tmp = timestamp.low;
- mData[3] = (unsigned char) tmp;
- tmp >>= 8;
- mData[2] = (unsigned char) tmp;
- tmp >>= 8;
- mData[1] = (unsigned char) tmp;
- tmp >>= 8;
- mData[0] = (unsigned char) tmp;
-
- tmp = (U16) timestamp.high;
- mData[5] = (unsigned char) tmp;
- tmp >>= 8;
- mData[4] = (unsigned char) tmp;
+ memcpy(mData + 10, node_id, 6); /* Flawfinder: ignore */
+ U32 tmp;
+ tmp = timestamp.low;
+ mData[3] = (unsigned char)tmp;
+ tmp >>= 8;
+ mData[2] = (unsigned char)tmp;
+ tmp >>= 8;
+ mData[1] = (unsigned char)tmp;
+ tmp >>= 8;
+ mData[0] = (unsigned char)tmp;
- tmp = (timestamp.high >> 16) | 0x1000;
- mData[7] = (unsigned char) tmp;
- tmp >>= 8;
- mData[6] = (unsigned char) tmp;
+ tmp = (U16)timestamp.high;
+ mData[5] = (unsigned char)tmp;
+ tmp >>= 8;
+ mData[4] = (unsigned char)tmp;
- tmp = our_clock_seq;
+ tmp = (timestamp.high >> 16) | 0x1000;
+ mData[7] = (unsigned char)tmp;
+ tmp >>= 8;
+ mData[6] = (unsigned char)tmp;
- mData[9] = (unsigned char) tmp;
- tmp >>= 8;
- mData[8] = (unsigned char) tmp;
+ tmp = our_clock_seq;
- HBXXH128::digest(*this, (const void*)mData, 16);
+ mData[9] = (unsigned char)tmp;
+ tmp >>= 8;
+ mData[8] = (unsigned char)tmp;
+
+ HBXXH128::digest(*this, (const void*)mData, 16);
}
void LLUUID::generate(const std::string& hash_string)
{
- HBXXH128::digest(*this, hash_string);
+ HBXXH128::digest(*this, hash_string);
}
U32 LLUUID::getRandomSeed()
{
- static unsigned char seed[16]; /* Flawfinder: ignore */
-
- getNodeID(&seed[0]);
+ static unsigned char seed[16]; /* Flawfinder: ignore */
- // Incorporate the pid into the seed to prevent
- // processes that start on the same host at the same
- // time from generating the same seed.
- pid_t pid = LLApp::getPid();
+ getNodeID(&seed[0]);
- seed[6]=(unsigned char)(pid >> 8);
- seed[7]=(unsigned char)(pid);
- getSystemTime((uuid_time_t *)(&seed[8]));
+ // Incorporate the pid into the seed to prevent
+ // processes that start on the same host at the same
+ // time from generating the same seed.
+ pid_t pid = LLApp::getPid();
+
+ seed[6] = (unsigned char)(pid >> 8);
+ seed[7] = (unsigned char)(pid);
+ getSystemTime((uuid_time_t*)(&seed[8]));
U64 seed64 = HBXXH64::digest((const void*)seed, 16);
return U32(seed64) ^ U32(seed64 >> 32);
@@ -890,92 +891,92 @@ U32 LLUUID::getRandomSeed()
BOOL LLUUID::parseUUID(const std::string& buf, LLUUID* value)
{
- if( buf.empty() || value == NULL)
- {
- return FALSE;
- }
+ if (buf.empty() || value == NULL)
+ {
+ return FALSE;
+ }
- std::string temp( buf );
- LLStringUtil::trim(temp);
- if( LLUUID::validate( temp ) )
- {
- value->set( temp );
- return TRUE;
- }
- return FALSE;
+ std::string temp(buf);
+ LLStringUtil::trim(temp);
+ if (LLUUID::validate(temp))
+ {
+ value->set(temp);
+ return TRUE;
+ }
+ return FALSE;
}
//static
LLUUID LLUUID::generateNewID(std::string hash_string)
{
- LLUUID new_id;
- if (hash_string.empty())
- {
- new_id.generate();
- }
- else
- {
- new_id.generate(hash_string);
- }
- return new_id;
+ LLUUID new_id;
+ if (hash_string.empty())
+ {
+ new_id.generate();
+ }
+ else
+ {
+ new_id.generate(hash_string);
+ }
+ return new_id;
}
LLAssetID LLTransactionID::makeAssetID(const LLUUID& session) const
{
- LLAssetID result;
- if (isNull())
- {
- result.setNull();
- }
- else
- {
- combine(session, result);
- }
- return result;
+ LLAssetID result;
+ if (isNull())
+ {
+ result.setNull();
+ }
+ else
+ {
+ combine(session, result);
+ }
+ return result;
}
// Construct
LLUUID::LLUUID()
{
- setNull();
+ setNull();
}
// Faster than copying from memory
- void LLUUID::setNull()
+void LLUUID::setNull()
{
- U32 *word = (U32 *)mData;
- word[0] = 0;
- word[1] = 0;
- word[2] = 0;
- word[3] = 0;
+ U32* word = (U32*)mData;
+ word[0] = 0;
+ word[1] = 0;
+ word[2] = 0;
+ word[3] = 0;
}
// Compare
- bool LLUUID::operator==(const LLUUID& rhs) const
+bool LLUUID::operator==(const LLUUID& rhs) const
{
- U32 *tmp = (U32 *)mData;
- U32 *rhstmp = (U32 *)rhs.mData;
- // Note: binary & to avoid branching
- return
- (tmp[0] == rhstmp[0]) &
- (tmp[1] == rhstmp[1]) &
- (tmp[2] == rhstmp[2]) &
- (tmp[3] == rhstmp[3]);
+ U32* tmp = (U32*)mData;
+ U32* rhstmp = (U32*)rhs.mData;
+ // Note: binary & to avoid branching
+ return
+ (tmp[0] == rhstmp[0]) &
+ (tmp[1] == rhstmp[1]) &
+ (tmp[2] == rhstmp[2]) &
+ (tmp[3] == rhstmp[3]);
}
- bool LLUUID::operator!=(const LLUUID& rhs) const
+bool LLUUID::operator!=(const LLUUID& rhs) const
{
- U32 *tmp = (U32 *)mData;
- U32 *rhstmp = (U32 *)rhs.mData;
- // Note: binary | to avoid branching
- return
- (tmp[0] != rhstmp[0]) |
- (tmp[1] != rhstmp[1]) |
- (tmp[2] != rhstmp[2]) |
- (tmp[3] != rhstmp[3]);
+ U32* tmp = (U32*)mData;
+ U32* rhstmp = (U32*)rhs.mData;
+ // Note: binary | to avoid branching
+ return
+ (tmp[0] != rhstmp[0]) |
+ (tmp[1] != rhstmp[1]) |
+ (tmp[2] != rhstmp[2]) |
+ (tmp[3] != rhstmp[3]);
}
/*
@@ -983,94 +984,94 @@ LLUUID::LLUUID()
// to integers, among other things. Use isNull() or notNull().
LLUUID::operator bool() const
{
- U32 *word = (U32 *)mData;
- return (word[0] | word[1] | word[2] | word[3]) > 0;
+ U32 *word = (U32 *)mData;
+ return (word[0] | word[1] | word[2] | word[3]) > 0;
}
*/
- BOOL LLUUID::notNull() const
+BOOL LLUUID::notNull() const
{
- U32 *word = (U32 *)mData;
- return (word[0] | word[1] | word[2] | word[3]) > 0;
+ U32* word = (U32*)mData;
+ return (word[0] | word[1] | word[2] | word[3]) > 0;
}
// Faster than == LLUUID::null because doesn't require
// as much memory access.
- BOOL LLUUID::isNull() const
+BOOL LLUUID::isNull() const
{
- U32 *word = (U32 *)mData;
- // If all bits are zero, return !0 == TRUE
- return !(word[0] | word[1] | word[2] | word[3]);
+ U32* word = (U32*)mData;
+ // If all bits are zero, return !0 == TRUE
+ return !(word[0] | word[1] | word[2] | word[3]);
}
- LLUUID::LLUUID(const char *in_string)
+LLUUID::LLUUID(const char* in_string)
{
- if (!in_string || in_string[0] == 0)
- {
- setNull();
- return;
- }
-
- set(in_string);
+ if (!in_string || in_string[0] == 0)
+ {
+ setNull();
+ return;
+ }
+
+ set(in_string);
}
- LLUUID::LLUUID(const std::string& in_string)
+LLUUID::LLUUID(const std::string& in_string)
{
- if (in_string.empty())
- {
- setNull();
- return;
- }
+ if (in_string.empty())
+ {
+ setNull();
+ return;
+ }
- set(in_string);
+ set(in_string);
}
// IW: DON'T "optimize" these w/ U32s or you'll scoogie the sort order
// IW: this will make me very sad
- bool LLUUID::operator<(const LLUUID &rhs) const
+bool LLUUID::operator<(const LLUUID& rhs) const
{
- U32 i;
- for( i = 0; i < (UUID_BYTES - 1); i++ )
- {
- if( mData[i] != rhs.mData[i] )
- {
- return (mData[i] < rhs.mData[i]);
- }
- }
- return (mData[UUID_BYTES - 1] < rhs.mData[UUID_BYTES - 1]);
+ U32 i;
+ for (i = 0; i < (UUID_BYTES - 1); i++)
+ {
+ if (mData[i] != rhs.mData[i])
+ {
+ return (mData[i] < rhs.mData[i]);
+ }
+ }
+ return (mData[UUID_BYTES - 1] < rhs.mData[UUID_BYTES - 1]);
}
- bool LLUUID::operator>(const LLUUID &rhs) const
+bool LLUUID::operator>(const LLUUID& rhs) const
{
- U32 i;
- for( i = 0; i < (UUID_BYTES - 1); i++ )
- {
- if( mData[i] != rhs.mData[i] )
- {
- return (mData[i] > rhs.mData[i]);
- }
- }
- return (mData[UUID_BYTES - 1] > rhs.mData[UUID_BYTES - 1]);
+ U32 i;
+ for (i = 0; i < (UUID_BYTES - 1); i++)
+ {
+ if (mData[i] != rhs.mData[i])
+ {
+ return (mData[i] > rhs.mData[i]);
+ }
+ }
+ return (mData[UUID_BYTES - 1] > rhs.mData[UUID_BYTES - 1]);
}
- U16 LLUUID::getCRC16() const
+U16 LLUUID::getCRC16() const
{
- // A UUID is 16 bytes, or 8 shorts.
- U16 *short_data = (U16*)mData;
- U16 out = 0;
- out += short_data[0];
- out += short_data[1];
- out += short_data[2];
- out += short_data[3];
- out += short_data[4];
- out += short_data[5];
- out += short_data[6];
- out += short_data[7];
- return out;
+ // A UUID is 16 bytes, or 8 shorts.
+ U16* short_data = (U16*)mData;
+ U16 out = 0;
+ out += short_data[0];
+ out += short_data[1];
+ out += short_data[2];
+ out += short_data[3];
+ out += short_data[4];
+ out += short_data[5];
+ out += short_data[6];
+ out += short_data[7];
+ return out;
}
- U32 LLUUID::getCRC32() const
+U32 LLUUID::getCRC32() const
{
- U32 *tmp = (U32*)mData;
- return tmp[0] + tmp[1] + tmp[2] + tmp[3];
+ U32* tmp = (U32*)mData;
+ return tmp[0] + tmp[1] + tmp[2] + tmp[3];
}
diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp
index e5eda1eac7..06c74bdba0 100644
--- a/indra/llcommon/llworkerthread.cpp
+++ b/indra/llcommon/llworkerthread.cpp
@@ -73,6 +73,7 @@ void LLWorkerThread::clearDeleteList()
{
worker->mRequestHandle = LLWorkerThread::nullHandle();
worker->clearFlags(LLWorkerClass::WCF_HAVE_WORK);
+ worker->clearFlags(LLWorkerClass::WCF_WORKING);
delete worker;
}
mDeleteList.clear() ;
@@ -97,6 +98,7 @@ size_t LLWorkerThread::update(F32 max_time_ms)
{
if (worker->getFlags(LLWorkerClass::WCF_WORK_FINISHED))
{
+ worker->setFlags(LLWorkerClass::WCF_DELETE_REQUESTED);
delete_list.push_back(worker);
mDeleteList.erase(curiter);
}
@@ -130,11 +132,11 @@ size_t LLWorkerThread::update(F32 max_time_ms)
//----------------------------------------------------------------------------
-LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority)
+LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workerclass, S32 param)
{
handle_t handle = generateHandle();
- WorkRequest* req = new WorkRequest(handle, priority, workerclass, param);
+ WorkRequest* req = new WorkRequest(handle, workerclass, param);
bool res = addRequest(req);
if (!res)
@@ -157,8 +159,8 @@ void LLWorkerThread::deleteWorker(LLWorkerClass* workerclass)
//============================================================================
// Runs on its OWN thread
-LLWorkerThread::WorkRequest::WorkRequest(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param) :
- LLQueuedThread::QueuedRequest(handle, priority),
+LLWorkerThread::WorkRequest::WorkRequest(handle_t handle, LLWorkerClass* workerclass, S32 param) :
+ LLQueuedThread::QueuedRequest(handle),
mWorkerClass(workerclass),
mParam(param)
{
@@ -177,6 +179,7 @@ void LLWorkerThread::WorkRequest::deleteRequest()
// virtual
bool LLWorkerThread::WorkRequest::processRequest()
{
+ LL_PROFILE_ZONE_SCOPED;
LLWorkerClass* workerclass = getWorkerClass();
workerclass->setWorking(true);
bool complete = workerclass->doWork(getParam());
@@ -187,6 +190,7 @@ bool LLWorkerThread::WorkRequest::processRequest()
// virtual
void LLWorkerThread::WorkRequest::finishRequest(bool completed)
{
+ LL_PROFILE_ZONE_SCOPED;
LLWorkerClass* workerclass = getWorkerClass();
workerclass->finishWork(getParam(), completed);
U32 flags = LLWorkerClass::WCF_WORK_FINISHED | (completed ? 0 : LLWorkerClass::WCF_WORK_ABORTED);
@@ -200,7 +204,6 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
: mWorkerThread(workerthread),
mWorkerClassName(name),
mRequestHandle(LLWorkerThread::nullHandle()),
- mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
mMutex(),
mWorkFlags(0)
{
@@ -289,7 +292,7 @@ bool LLWorkerClass::yield()
//----------------------------------------------------------------------------
// calls startWork, adds doWork() to queue
-void LLWorkerClass::addWork(S32 param, U32 priority)
+void LLWorkerClass::addWork(S32 param)
{
mMutex.lock();
llassert_always(!(mWorkFlags & (WCF_WORKING|WCF_HAVE_WORK)));
@@ -303,7 +306,7 @@ void LLWorkerClass::addWork(S32 param, U32 priority)
startWork(param);
clearFlags(WCF_WORK_FINISHED|WCF_WORK_ABORTED);
setFlags(WCF_HAVE_WORK);
- mRequestHandle = mWorkerThread->addWorkRequest(this, param, priority);
+ mRequestHandle = mWorkerThread->addWorkRequest(this, param);
mMutex.unlock();
}
@@ -318,7 +321,6 @@ void LLWorkerClass::abortWork(bool autocomplete)
if (mRequestHandle != LLWorkerThread::nullHandle())
{
mWorkerThread->abortRequest(mRequestHandle, autocomplete);
- mWorkerThread->setPriority(mRequestHandle, LLQueuedThread::PRIORITY_IMMEDIATE);
setFlags(WCF_ABORT_REQUESTED);
}
mMutex.unlock();
@@ -392,16 +394,5 @@ void LLWorkerClass::scheduleDelete()
}
}
-void LLWorkerClass::setPriority(U32 priority)
-{
- mMutex.lock();
- if (mRequestHandle != LLWorkerThread::nullHandle() && mRequestPriority != priority)
- {
- mRequestPriority = priority;
- mWorkerThread->setPriority(mRequestHandle, priority);
- }
- mMutex.unlock();
-}
-
//============================================================================
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index e3004d7242..bf94c84090 100644
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -56,7 +56,7 @@ public:
virtual ~WorkRequest(); // use deleteRequest()
public:
- WorkRequest(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param);
+ WorkRequest(handle_t handle, LLWorkerClass* workerclass, S32 param);
S32 getParam()
{
@@ -90,7 +90,7 @@ public:
/*virtual*/ size_t update(F32 max_time_ms);
- handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL);
+ handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param);
S32 getNumDeletes() { return (S32)mDeleteList.size(); } // debug
@@ -151,10 +151,6 @@ public:
bool isWorking() { return getFlags(WCF_WORKING); }
bool wasAborted() { return getFlags(WCF_ABORT_REQUESTED); }
- // setPriority(): changes the priority of a request
- void setPriority(U32 priority);
- U32 getPriority() { return mRequestPriority; }
-
const std::string& getName() const { return mWorkerClassName; }
protected:
@@ -169,7 +165,7 @@ protected:
void setWorkerThread(LLWorkerThread* workerthread);
// addWork(): calls startWork, adds doWork() to queue
- void addWork(S32 param, U32 priority = LLWorkerThread::PRIORITY_NORMAL);
+ void addWork(S32 param);
// abortWork(): requests that work be aborted
void abortWork(bool autocomplete);
@@ -193,7 +189,6 @@ protected:
LLWorkerThread* mWorkerThread;
std::string mWorkerClassName;
handle_t mRequestHandle;
- U32 mRequestPriority; // last priority set
private:
LLMutex mMutex;
diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp
index 3ae48a2532..7197dedfbf 100644
--- a/indra/llcommon/tests/llleap_test.cpp
+++ b/indra/llcommon/tests/llleap_test.cpp
@@ -17,8 +17,6 @@
// std headers
#include
// external library headers
-#include
-#include
// other Linden headers
#include "../test/lltut.h"
#include "../test/namedtempfile.h"
@@ -30,10 +28,6 @@
#include "stringize.h"
#include "StringVec.h"
-using boost::assign::list_of;
-
-StringVec sv(const StringVec& listof) { return listof; }
-
#if defined(LL_WINDOWS)
#define sleep(secs) _sleep((secs) * 1000)
@@ -104,17 +98,12 @@ namespace tut
llleap_data():
reader(".py",
// This logic is adapted from vita.viewerclient.receiveEvent()
- boost::phoenix::placeholders::arg1 <<
+ [](std::ostream& out){ out <<
"import re\n"
"import os\n"
"import sys\n"
"\n"
- "try:\n"
- // new freestanding llsd package
- " import llsd\n"
- "except ImportError:\n"
- // older llbase.llsd module
- " from llbase import llsd\n"
+ "import llsd\n"
"\n"
"class ProtocolError(Exception):\n"
" def __init__(self, msg, data):\n"
@@ -193,7 +182,7 @@ namespace tut
"def request(pump, data):\n"
" # we expect 'data' is a dict\n"
" data['reply'] = _reply\n"
- " send(pump, data)\n"),
+ " send(pump, data)\n";}),
// Get the actual pathname of the NamedExtTempFile and trim off
// the ".py" extension. (We could cache reader.getName() in a
// separate member variable, but I happen to know getName() just
@@ -218,14 +207,14 @@ namespace tut
void object::test<1>()
{
set_test_name("multiple LLLeap instances");
- NamedTempFile script("py",
- "import time\n"
- "time.sleep(1)\n");
+ NamedExtTempFile script("py",
+ "import time\n"
+ "time.sleep(1)\n");
LLLeapVector instances;
instances.push_back(LLLeap::create(get_test_name(),
- sv(list_of(PYTHON)(script.getName())))->getWeak());
+ StringVec{PYTHON, script.getName()})->getWeak());
instances.push_back(LLLeap::create(get_test_name(),
- sv(list_of(PYTHON)(script.getName())))->getWeak());
+ StringVec{PYTHON, script.getName()})->getWeak());
// In this case we're simply establishing that two LLLeap instances
// can coexist without throwing exceptions or bombing in any other
// way. Wait for them to terminate.
@@ -236,10 +225,10 @@ namespace tut
void object::test<2>()
{
set_test_name("stderr to log");
- NamedTempFile script("py",
- "import sys\n"
- "sys.stderr.write('''Hello from Python!\n"
- "note partial line''')\n");
+ NamedExtTempFile script("py",
+ "import sys\n"
+ "sys.stderr.write('''Hello from Python!\n"
+ "note partial line''')\n");
StringVec vcommand{ PYTHON, script.getName() };
CaptureLog log(LLError::LEVEL_INFO);
waitfor(LLLeap::create(get_test_name(), vcommand));
@@ -251,11 +240,11 @@ namespace tut
void object::test<3>()
{
set_test_name("bad stdout protocol");
- NamedTempFile script("py",
- "print('Hello from Python!')\n");
+ NamedExtTempFile script("py",
+ "print('Hello from Python!')\n");
CaptureLog log(LLError::LEVEL_WARN);
waitfor(LLLeap::create(get_test_name(),
- sv(list_of(PYTHON)(script.getName()))));
+ StringVec{PYTHON, script.getName()}));
ensure_contains("error log line",
log.messageWith("invalid protocol"), "Hello from Python!");
}
@@ -264,13 +253,13 @@ namespace tut
void object::test<4>()
{
set_test_name("leftover stdout");
- NamedTempFile script("py",
- "import sys\n"
- // note lack of newline
- "sys.stdout.write('Hello from Python!')\n");
+ NamedExtTempFile script("py",
+ "import sys\n"
+ // note lack of newline
+ "sys.stdout.write('Hello from Python!')\n");
CaptureLog log(LLError::LEVEL_WARN);
waitfor(LLLeap::create(get_test_name(),
- sv(list_of(PYTHON)(script.getName()))));
+ StringVec{PYTHON, script.getName()}));
ensure_contains("error log line",
log.messageWith("Discarding"), "Hello from Python!");
}
@@ -279,12 +268,12 @@ namespace tut
void object::test<5>()
{
set_test_name("bad stdout len prefix");
- NamedTempFile script("py",
- "import sys\n"
- "sys.stdout.write('5a2:something')\n");
+ NamedExtTempFile script("py",
+ "import sys\n"
+ "sys.stdout.write('5a2:something')\n");
CaptureLog log(LLError::LEVEL_WARN);
waitfor(LLLeap::create(get_test_name(),
- sv(list_of(PYTHON)(script.getName()))));
+ StringVec{PYTHON, script.getName()}));
ensure_contains("error log line",
log.messageWith("invalid protocol"), "5a2:");
}
@@ -386,17 +375,18 @@ namespace tut
set_test_name("round trip");
AckAPI api;
Result result;
- NamedTempFile script("py",
- boost::phoenix::placeholders::arg1 <<
- "from " << reader_module << " import *\n"
- // make a request on our little API
- "request(pump='" << api.getName() << "', data={})\n"
- // wait for its response
- "resp = get()\n"
- "result = '' if resp == dict(pump=replypump(), data='ack')\\\n"
- " else 'bad: ' + str(resp)\n"
- "send(pump='" << result.getName() << "', data=result)\n");
- waitfor(LLLeap::create(get_test_name(), sv(list_of(PYTHON)(script.getName()))));
+ NamedExtTempFile script("py",
+ [&](std::ostream& out){ out <<
+ "from " << reader_module << " import *\n"
+ // make a request on our little API
+ "request(pump='" << api.getName() << "', data={})\n"
+ // wait for its response
+ "resp = get()\n"
+ "result = '' if resp == dict(pump=replypump(), data='ack')\\\n"
+ " else 'bad: ' + str(resp)\n"
+ "send(pump='" << result.getName() << "', data=result)\n";});
+ waitfor(LLLeap::create(get_test_name(),
+ StringVec{PYTHON, script.getName()}));
result.ensure();
}
@@ -424,38 +414,38 @@ namespace tut
// iterations etc. in OS pipes and the LLLeap/LLProcess implementation.
ReqIDAPI api;
Result result;
- NamedTempFile script("py",
- boost::phoenix::placeholders::arg1 <<
- "import sys\n"
- "from " << reader_module << " import *\n"
- // Note that since reader imports llsd, this
- // 'import *' gets us llsd too.
- "sample = llsd.format_notation(dict(pump='" <<
- api.getName() << "', data=dict(reqid=999999, reply=replypump())))\n"
- // The whole packet has length prefix too: "len:data"
- "samplen = len(str(len(sample))) + 1 + len(sample)\n"
- // guess how many messages it will take to
- // accumulate BUFFERED_LENGTH
- "count = int(" << BUFFERED_LENGTH << "/samplen)\n"
- "print('Sending %s requests' % count, file=sys.stderr)\n"
- "for i in range(count):\n"
- " request('" << api.getName() << "', dict(reqid=i))\n"
- // The assumption in this specific test that
- // replies will arrive in the same order as
- // requests is ONLY valid because the API we're
- // invoking sends replies instantly. If the API
- // had to wait for some external event before
- // sending its reply, replies could arrive in
- // arbitrary order, and we'd have to tick them
- // off from a set.
- "result = ''\n"
- "for i in range(count):\n"
- " resp = get()\n"
- " if resp['data']['reqid'] != i:\n"
- " result = 'expected reqid=%s in %s' % (i, resp)\n"
- " break\n"
- "send(pump='" << result.getName() << "', data=result)\n");
- waitfor(LLLeap::create(get_test_name(), sv(list_of(PYTHON)(script.getName()))),
+ NamedExtTempFile script("py",
+ [&](std::ostream& out){ out <<
+ "import sys\n"
+ "from " << reader_module << " import *\n"
+ // Note that since reader imports llsd, this
+ // 'import *' gets us llsd too.
+ "sample = llsd.format_notation(dict(pump='" <<
+ api.getName() << "', data=dict(reqid=999999, reply=replypump())))\n"
+ // The whole packet has length prefix too: "len:data"
+ "samplen = len(str(len(sample))) + 1 + len(sample)\n"
+ // guess how many messages it will take to
+ // accumulate BUFFERED_LENGTH
+ "count = int(" << BUFFERED_LENGTH << "/samplen)\n"
+ "print('Sending %s requests' % count, file=sys.stderr)\n"
+ "for i in range(count):\n"
+ " request('" << api.getName() << "', dict(reqid=i))\n"
+ // The assumption in this specific test that
+ // replies will arrive in the same order as
+ // requests is ONLY valid because the API we're
+ // invoking sends replies instantly. If the API
+ // had to wait for some external event before
+ // sending its reply, replies could arrive in
+ // arbitrary order, and we'd have to tick them
+ // off from a set.
+ "result = ''\n"
+ "for i in range(count):\n"
+ " resp = get()\n"
+ " if resp['data']['reqid'] != i:\n"
+ " result = 'expected reqid=%s in %s' % (i, resp)\n"
+ " break\n"
+ "send(pump='" << result.getName() << "', data=result)\n";});
+ waitfor(LLLeap::create(get_test_name(), StringVec{PYTHON, script.getName()}),
300); // needs more realtime than most tests
result.ensure();
}
@@ -467,65 +457,62 @@ namespace tut
{
ReqIDAPI api;
Result result;
- NamedTempFile script("py",
- boost::phoenix::placeholders::arg1 <<
- "import sys\n"
- "from " << reader_module << " import *\n"
- // Generate a very large string value.
- "desired = int(sys.argv[1])\n"
- // 7 chars per item: 6 digits, 1 comma
- "count = int((desired - 50)/7)\n"
- "large = ''.join('%06d,' % i for i in range(count))\n"
- // Pass 'large' as reqid because we know the API
- // will echo reqid, and we want to receive it back.
- "request('" << api.getName() << "', dict(reqid=large))\n"
- "try:\n"
- " resp = get()\n"
- "except ParseError as e:\n"
- " # try to find where e.data diverges from expectation\n"
- // Normally we'd expect a 'pump' key in there,
- // too, with value replypump(). But Python
- // serializes keys in a different order than C++,
- // so incoming data start with 'data'.
- // Truthfully, though, if we get as far as 'pump'
- // before we find a difference, something's very
- // strange.
- " expect = llsd.format_notation(dict(data=dict(reqid=large)))\n"
- " chunk = 40\n"
- " for offset in range(0, max(len(e.data), len(expect)), chunk):\n"
- " if e.data[offset:offset+chunk] != \\\n"
- " expect[offset:offset+chunk]:\n"
- " print('Offset %06d: expect %r,\\n'\\\n"
- " ' get %r' %\\\n"
- " (offset,\n"
- " expect[offset:offset+chunk],\n"
- " e.data[offset:offset+chunk]),\n"
- " file=sys.stderr)\n"
- " break\n"
- " else:\n"
- " print('incoming data matches expect?!', file=sys.stderr)\n"
- " send('" << result.getName() << "', '%s: %s' % (e.__class__.__name__, e))\n"
- " sys.exit(1)\n"
- "\n"
- "echoed = resp['data']['reqid']\n"
- "if echoed == large:\n"
- " send('" << result.getName() << "', '')\n"
- " sys.exit(0)\n"
- // Here we know echoed did NOT match; try to find where
- "for i in range(count):\n"
- " start = 7*i\n"
- " end = 7*(i+1)\n"
- " if end > len(echoed)\\\n"
- " or echoed[start:end] != large[start:end]:\n"
- " send('" << result.getName() << "',\n"
- " 'at offset %s, expected %r but got %r' %\n"
- " (start, large[start:end], echoed[start:end]))\n"
- "sys.exit(1)\n");
+ NamedExtTempFile script("py",
+ [&](std::ostream& out){ out <<
+ "import sys\n"
+ "from " << reader_module << " import *\n"
+ // Generate a very large string value.
+ "desired = int(sys.argv[1])\n"
+ // 7 chars per item: 6 digits, 1 comma
+ "count = int((desired - 50)/7)\n"
+ "large = ''.join('%06d,' % i for i in range(count))\n"
+ // Pass 'large' as reqid because we know the API
+ // will echo reqid, and we want to receive it back.
+ "request('" << api.getName() << "', dict(reqid=large))\n"
+ "try:\n"
+ " resp = get()\n"
+ "except ParseError as e:\n"
+ " # try to find where e.data diverges from expectation\n"
+ // Normally we'd expect a 'pump' key in there,
+ // too, with value replypump(). But Python
+ // serializes keys in a different order than C++,
+ // so incoming data start with 'data'.
+ // Truthfully, though, if we get as far as 'pump'
+ // before we find a difference, something's very
+ // strange.
+ " expect = llsd.format_notation(dict(data=dict(reqid=large)))\n"
+ " chunk = 40\n"
+ " for offset in range(0, max(len(e.data), len(expect)), chunk):\n"
+ " if e.data[offset:offset+chunk] != \\\n"
+ " expect[offset:offset+chunk]:\n"
+ " print('Offset %06d: expect %r,\\n'\\\n"
+ " ' get %r' %\\\n"
+ " (offset,\n"
+ " expect[offset:offset+chunk],\n"
+ " e.data[offset:offset+chunk]),\n"
+ " file=sys.stderr)\n"
+ " break\n"
+ " else:\n"
+ " print('incoming data matches expect?!', file=sys.stderr)\n"
+ " send('" << result.getName() << "', '%s: %s' % (e.__class__.__name__, e))\n"
+ " sys.exit(1)\n"
+ "\n"
+ "echoed = resp['data']['reqid']\n"
+ "if echoed == large:\n"
+ " send('" << result.getName() << "', '')\n"
+ " sys.exit(0)\n"
+ // Here we know echoed did NOT match; try to find where
+ "for i in range(count):\n"
+ " start = 7*i\n"
+ " end = 7*(i+1)\n"
+ " if end > len(echoed)\\\n"
+ " or echoed[start:end] != large[start:end]:\n"
+ " send('" << result.getName() << "',\n"
+ " 'at offset %s, expected %r but got %r' %\n"
+ " (start, large[start:end], echoed[start:end]))\n"
+ "sys.exit(1)\n";});
waitfor(LLLeap::create(test_name,
- sv(list_of
- (PYTHON)
- (script.getName())
- (stringize(size)))),
+ StringVec{PYTHON, script.getName(), stringize(size)}),
180); // try a longer timeout
result.ensure();
}
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 81449b4a42..b6b297b8d7 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -151,8 +151,38 @@ struct PythonProcessLauncher
/// Launch Python script; verify that it launched
void launch()
{
- mPy = LLProcess::create(mParams);
- tut::ensure(STRINGIZE("Couldn't launch " << mDesc << " script"), bool(mPy));
+ try
+ {
+ mPy = LLProcess::create(mParams);
+ tut::ensure(STRINGIZE("Couldn't launch " << mDesc << " script"), bool(mPy));
+ }
+ catch (const tut::failure&)
+ {
+ // On Windows, if APR_LOG is set, our version of APR's
+ // apr_create_proc() logs to the specified file. If this test
+ // failed, try to report that log.
+ const char* APR_LOG = getenv("APR_LOG");
+ if (APR_LOG && *APR_LOG)
+ {
+ std::ifstream inf(APR_LOG);
+ if (! inf.is_open())
+ {
+ LL_WARNS() << "Couldn't open '" << APR_LOG << "'" << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << "==============================" << LL_ENDL;
+ LL_WARNS() << "From '" << APR_LOG << "':" << LL_ENDL;
+ std::string line;
+ while (std::getline(inf, line))
+ {
+ LL_WARNS() << line << LL_ENDL;
+ }
+ LL_WARNS() << "==============================" << LL_ENDL;
+ }
+ }
+ throw;
+ }
}
/// Run Python script and wait for it to complete.
@@ -191,7 +221,7 @@ struct PythonProcessLauncher
LLProcess::Params mParams;
LLProcessPtr mPy;
std::string mDesc;
- NamedTempFile mScript;
+ NamedExtTempFile mScript;
};
/// convenience function for PythonProcessLauncher::run()
@@ -214,30 +244,26 @@ static std::string python_out(const std::string& desc, const CONTENT& script)
class NamedTempDir: public boost::noncopyable
{
public:
- // Use python() function to create a temp directory: I've found
- // nothing in either Boost.Filesystem or APR quite like Python's
- // tempfile.mkdtemp().
- // Special extra bonus: on Mac, mkdtemp() reports a pathname
- // starting with /var/folders/something, whereas that's really a
- // symlink to /private/var/folders/something. Have to use
- // realpath() to compare properly.
NamedTempDir():
- mPath(python_out("mkdtemp()",
- "from __future__ import with_statement\n"
- "import os.path, sys, tempfile\n"
- "with open(sys.argv[1], 'w') as f:\n"
- " f.write(os.path.normcase(os.path.normpath(os.path.realpath(tempfile.mkdtemp()))))\n"))
- {}
+ mPath(NamedTempFile::temp_path()),
+ mCreated(boost::filesystem::create_directories(mPath))
+ {
+ mPath = boost::filesystem::canonical(mPath);
+ }
~NamedTempDir()
{
- aprchk(apr_dir_remove(mPath.c_str(), gAPRPoolp));
+ if (mCreated)
+ {
+ boost::filesystem::remove_all(mPath);
+ }
}
- std::string getName() const { return mPath; }
+ std::string getName() const { return mPath.string(); }
private:
- std::string mPath;
+ boost::filesystem::path mPath;
+ bool mCreated;
};
/*****************************************************************************
@@ -355,7 +381,7 @@ namespace tut
set_test_name("raw APR nonblocking I/O");
// Create a script file in a temporary place.
- NamedTempFile script("py",
+ NamedExtTempFile script("py",
"from __future__ import print_function" EOL
"import sys" EOL
"import time" EOL
@@ -565,7 +591,13 @@ namespace tut
" f.write(os.path.normcase(os.path.normpath(os.getcwd())))\n");
// Before running, call setWorkingDirectory()
py.mParams.cwd = tempdir.getName();
- ensure_equals("os.getcwd()", py.run_read(), tempdir.getName());
+ std::string expected{ tempdir.getName() };
+#if LL_WINDOWS
+ // SIGH, don't get tripped up by "C:" != "c:" --
+ // but on the Mac, using tolower() fails because "/users" != "/Users"!
+ expected = utf8str_tolower(expected);
+#endif
+ ensure_equals("os.getcwd()", py.run_read(), expected);
}
template<> template<>
diff --git a/indra/llcommon/tests/llrand_test.cpp b/indra/llcommon/tests/llrand_test.cpp
index 383e6f9e0a..ac5a33d0ba 100644
--- a/indra/llcommon/tests/llrand_test.cpp
+++ b/indra/llcommon/tests/llrand_test.cpp
@@ -29,7 +29,23 @@
#include "../test/lltut.h"
#include "../llrand.h"
+#include "stringize.h"
+// In llrand.h, every function is documented to return less than the high end
+// -- specifically, because you can pass a negative extent, they're documented
+// never to return a value equal to the extent.
+// So that we don't need two different versions of ensure_in_range(), when
+// testing extent < 0, negate the return value and the extent before passing
+// into ensure_in_range().
+template
+void ensure_in_range(const std::string_view& name,
+ NUMBER value, NUMBER low, NUMBER high)
+{
+ auto failmsg{ stringize(name, " >= ", low, " (", value, ')') };
+ tut::ensure(failmsg, (value >= low));
+ failmsg = stringize(name, " < ", high, " (", value, ')');
+ tut::ensure(failmsg, (value < high));
+}
namespace tut
{
@@ -44,84 +60,65 @@ namespace tut
template<> template<>
void random_object_t::test<1>()
{
- F32 number = 0.0f;
for(S32 ii = 0; ii < 100000; ++ii)
{
- number = ll_frand();
- ensure("frand >= 0", (number >= 0.0f));
- ensure("frand < 1", (number < 1.0f));
+ ensure_in_range("frand", ll_frand(), 0.0f, 1.0f);
}
}
template<> template<>
void random_object_t::test<2>()
{
- F64 number = 0.0f;
for(S32 ii = 0; ii < 100000; ++ii)
{
- number = ll_drand();
- ensure("drand >= 0", (number >= 0.0));
- ensure("drand < 1", (number < 1.0));
+ ensure_in_range("drand", ll_drand(), 0.0, 1.0);
}
}
template<> template<>
void random_object_t::test<3>()
{
- F32 number = 0.0f;
for(S32 ii = 0; ii < 100000; ++ii)
{
- number = ll_frand(2.0f) - 1.0f;
- ensure("frand >= 0", (number >= -1.0f));
- ensure("frand < 1", (number <= 1.0f));
+ ensure_in_range("frand(2.0f)", ll_frand(2.0f) - 1.0f, -1.0f, 1.0f);
}
}
template<> template<>
void random_object_t::test<4>()
{
- F32 number = 0.0f;
for(S32 ii = 0; ii < 100000; ++ii)
{
- number = ll_frand(-7.0);
- ensure("drand <= 0", (number <= 0.0));
- ensure("drand > -7", (number > -7.0));
+ // Negate the result so we don't have to allow a templated low-end
+ // comparison as well.
+ ensure_in_range("-frand(-7.0)", -ll_frand(-7.0), 0.0f, 7.0f);
}
}
template<> template<>
void random_object_t::test<5>()
{
- F64 number = 0.0f;
for(S32 ii = 0; ii < 100000; ++ii)
{
- number = ll_drand(-2.0);
- ensure("drand <= 0", (number <= 0.0));
- ensure("drand > -2", (number > -2.0));
+ ensure_in_range("-drand(-2.0)", -ll_drand(-2.0), 0.0, 2.0);
}
}
template<> template<>
void random_object_t::test<6>()
{
- S32 number = 0;
for(S32 ii = 0; ii < 100000; ++ii)
{
- number = ll_rand(100);
- ensure("rand >= 0", (number >= 0));
- ensure("rand < 100", (number < 100));
+ ensure_in_range("rand(100)", ll_rand(100), 0, 100);
}
}
template<> template<>
void random_object_t::test<7>()
{
- S32 number = 0;
for(S32 ii = 0; ii < 100000; ++ii)
{
- number = ll_rand(-127);
- ensure("rand <= 0", (number <= 0));
- ensure("rand > -127", (number > -127));
+ ensure_in_range("-rand(-127)", -ll_rand(-127), 0, 127);
}
}
}
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index acb2953b5b..ac40125f75 100644
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -45,11 +45,6 @@ typedef U32 uint32_t;
#endif
#include "boost/range.hpp"
-#include "boost/foreach.hpp"
-#include "boost/bind.hpp"
-#include "boost/phoenix/bind/bind_function.hpp"
-#include "boost/phoenix/core/argument.hpp"
-using namespace boost::phoenix;
#include "llsd.h"
#include "llsdserialize.h"
@@ -57,9 +52,11 @@ using namespace boost::phoenix;
#include "llformat.h"
#include "llmemorystream.h"
+#include "../test/hexdump.h"
#include "../test/lltut.h"
#include "../test/namedtempfile.h"
#include "stringize.h"
+#include "StringVec.h"
#include
typedef std::function FormatterFunction;
@@ -1796,16 +1793,12 @@ namespace tut
// helper for TestPythonCompatible
static std::string import_llsd("import os.path\n"
"import sys\n"
- "try:\n"
- // new freestanding llsd package
- " import llsd\n"
- "except ImportError:\n"
- // older llbase.llsd module
- " from llbase import llsd\n");
+ "import llsd\n");
// helper for TestPythonCompatible
- template
- void python(const std::string& desc, const CONTENT& script, int expect=0)
+ template
+ void python_expect(const std::string& desc, const CONTENT& script, int expect=0,
+ ARGS&&... args)
{
auto PYTHON(LLStringUtil::getenv("PYTHON"));
ensure("Set $PYTHON to the Python interpreter", !PYTHON.empty());
@@ -1816,7 +1809,8 @@ namespace tut
std::string q("\"");
std::string qPYTHON(q + PYTHON + q);
std::string qscript(q + scriptfile.getName() + q);
- int rc = _spawnl(_P_WAIT, PYTHON.c_str(), qPYTHON.c_str(), qscript.c_str(), NULL);
+ int rc = _spawnl(_P_WAIT, PYTHON.c_str(), qPYTHON.c_str(), qscript.c_str(),
+ std::forward(args)..., NULL);
if (rc == -1)
{
char buffer[256];
@@ -1832,6 +1826,10 @@ namespace tut
LLProcess::Params params;
params.executable = PYTHON;
params.args.add(scriptfile.getName());
+ for (const std::string& arg : StringVec{ std::forward(args)... })
+ {
+ params.args.add(arg);
+ }
LLProcessPtr py(LLProcess::create(params));
ensure(STRINGIZE("Couldn't launch " << desc << " script"), bool(py));
// Implementing timeout would mean messing with alarm() and
@@ -1866,6 +1864,14 @@ namespace tut
#endif
}
+ // helper for TestPythonCompatible
+ template
+ void python(const std::string& desc, const CONTENT& script, ARGS&&... args)
+ {
+ // plain python() expects rc 0
+ python_expect(desc, script, 0, std::forward(args)...);
+ }
+
struct TestPythonCompatible
{
TestPythonCompatible() {}
@@ -1880,10 +1886,10 @@ namespace tut
void TestPythonCompatibleObject::test<1>()
{
set_test_name("verify python()");
- python("hello",
- "import sys\n"
- "sys.exit(17)\n",
- 17); // expect nonzero rc
+ python_expect("hello",
+ "import sys\n"
+ "sys.exit(17)\n",
+ 17); // expect nonzero rc
}
template<> template<>
@@ -1899,7 +1905,7 @@ namespace tut
static void writeLLSDArray(const FormatterFunction& serialize,
std::ostream& out, const LLSD& array)
{
- for (const LLSD& item : llsd::inArray(array))
+ for (const LLSD& item: llsd::inArray(array))
{
// It's important to delimit the entries in this file somehow
// because, although Python's llsd.parse() can accept a file
@@ -1914,7 +1920,14 @@ namespace tut
auto buffstr{ buffer.str() };
int bufflen{ static_cast(buffstr.length()) };
out.write(reinterpret_cast(&bufflen), sizeof(bufflen));
+ LL_DEBUGS() << "Wrote length: "
+ << hexdump(reinterpret_cast(&bufflen),
+ sizeof(bufflen))
+ << LL_ENDL;
out.write(buffstr.c_str(), buffstr.length());
+ LL_DEBUGS() << "Wrote data: "
+ << hexmix(buffstr.c_str(), buffstr.length())
+ << LL_ENDL;
}
}
@@ -1943,10 +1956,10 @@ namespace tut
" else:\n"
" raise AssertionError('Too many data items')\n";
- // Create an llsdXXXXXX file containing 'data' serialized to
- // notation.
+ // Create an llsdXXXXXX file containing 'data' serialized per
+ // FormatterFunction.
NamedTempFile file("llsd",
- // NamedTempFile's boost::function constructor
+ // NamedTempFile's function constructor
// takes a callable. To this callable it passes the
// std::ostream with which it's writing the
// NamedTempFile.
@@ -1954,34 +1967,50 @@ namespace tut
(std::ostream& out)
{ writeLLSDArray(serialize, out, cdata); });
- python("read C++ " + desc,
- placeholders::arg1 <<
- import_llsd <<
- "from functools import partial\n"
- "import io\n"
- "import struct\n"
- "lenformat = struct.Struct('i')\n"
- "def parse_each(inf):\n"
- " for rawlen in iter(partial(inf.read, lenformat.size), b''):\n"
- " len = lenformat.unpack(rawlen)[0]\n"
- // Since llsd.parse() has no max_bytes argument, instead of
- // passing the input stream directly to parse(), read the item
- // into a distinct bytes object and parse that.
- " data = inf.read(len)\n"
- " try:\n"
- " frombytes = llsd.parse(data)\n"
- " except llsd.LLSDParseError as err:\n"
- " print(f'*** {err}')\n"
- " print(f'Bad content:\\n{data!r}')\n"
- " raise\n"
- // Also try parsing from a distinct stream.
- " stream = io.BytesIO(data)\n"
- " fromstream = llsd.parse(stream)\n"
- " assert frombytes == fromstream\n"
- " yield frombytes\n"
- << pydata <<
- // Don't forget raw-string syntax for Windows pathnames.
- "verify(parse_each(open(r'" << file.getName() << "', 'rb')))\n");
+ // 'debug' starts empty because it's intended as an output file
+ NamedTempFile debug("debug", "");
+
+ try
+ {
+ python("read C++ " + desc,
+ [&](std::ostream& out){ out <<
+ import_llsd <<
+ "from functools import partial\n"
+ "import io\n"
+ "import struct\n"
+ "lenformat = struct.Struct('i')\n"
+ "def parse_each(inf):\n"
+ " for rawlen in iter(partial(inf.read, lenformat.size), b''):\n"
+ " print('Read length:', ''.join(('%02x' % b) for b in rawlen),\n"
+ " file=debug)\n"
+ " len = lenformat.unpack(rawlen)[0]\n"
+ // Since llsd.parse() has no max_bytes argument, instead of
+ // passing the input stream directly to parse(), read the item
+ // into a distinct bytes object and parse that.
+ " data = inf.read(len)\n"
+ " print('Read data: ', repr(data), file=debug)\n"
+ " try:\n"
+ " frombytes = llsd.parse(data)\n"
+ " except llsd.LLSDParseError as err:\n"
+ " print(f'*** {err}')\n"
+ " print(f'Bad content:\\n{data!r}')\n"
+ " raise\n"
+ // Also try parsing from a distinct stream.
+ " stream = io.BytesIO(data)\n"
+ " fromstream = llsd.parse(stream)\n"
+ " assert frombytes == fromstream\n"
+ " yield frombytes\n"
+ << pydata <<
+ // Don't forget raw-string syntax for Windows pathnames.
+ "debug = open(r'" << debug.getName() << "', 'w')\n"
+ "verify(parse_each(open(r'" << file.getName() << "', 'rb')))\n";});
+ }
+ catch (const failure&)
+ {
+ LL_DEBUGS() << "Script debug output:" << LL_ENDL;
+ debug.peep_log();
+ throw;
+ }
}
template<> template<>
@@ -2068,7 +2097,7 @@ namespace tut
NamedTempFile file("llsd", "");
python("Python " + pyformatter,
- placeholders::arg1 <<
+ [&](std::ostream& out){ out <<
import_llsd <<
"import struct\n"
"lenformat = struct.Struct('i')\n"
@@ -2086,7 +2115,7 @@ namespace tut
" for item in DATA:\n"
" serialized = llsd." << pyformatter << "(item)\n"
" f.write(lenformat.pack(len(serialized)))\n"
- " f.write(serialized)\n");
+ " f.write(serialized)\n";});
std::ifstream inf(file.getName().c_str());
LLSD item;
diff --git a/indra/llcommon/tests/workqueue_test.cpp b/indra/llcommon/tests/workqueue_test.cpp
index 1d73f7aa0d..df16f4a46e 100644
--- a/indra/llcommon/tests/workqueue_test.cpp
+++ b/indra/llcommon/tests/workqueue_test.cpp
@@ -38,7 +38,7 @@ namespace tut
{
struct workqueue_data
{
- WorkQueue queue{"queue"};
+ WorkSchedule queue{"queue"};
};
typedef test_group workqueue_group;
typedef workqueue_group::object object;
@@ -49,8 +49,8 @@ namespace tut
{
set_test_name("name");
ensure_equals("didn't capture name", queue.getKey(), "queue");
- ensure("not findable", WorkQueue::getInstance("queue") == queue.getWeak().lock());
- WorkQueue q2;
+ ensure("not findable", WorkSchedule::getInstance("queue") == queue.getWeak().lock());
+ WorkSchedule q2;
ensure("has no name", LLStringUtil::startsWith(q2.getKey(), "WorkQueue"));
}
@@ -73,17 +73,21 @@ namespace tut
{
set_test_name("postEvery");
// record of runs
- using Shared = std::deque;
+ using Shared = std::deque;
// This is an example of how to share data between the originator of
- // postEvery(work) and the work item itself, since usually a WorkQueue
+ // postEvery(work) and the work item itself, since usually a WorkSchedule
// is used to dispatch work to a different thread. Neither of them
// should call any of LLCond's wait methods: you don't want to stall
// either the worker thread or the originating thread (conventionally
// main). Use LLCond or a subclass even if all you want to do is
// signal the work item that it can quit; consider LLOneShotCond.
LLCond data;
- auto start = WorkQueue::TimePoint::clock::now();
- auto interval = 100ms;
+ auto start = WorkSchedule::TimePoint::clock::now();
+ // 2s seems like a long time to wait, since it directly impacts the
+ // duration of this test program. Unfortunately GitHub's Mac runners
+ // are pretty wimpy, and we're getting spurious "too late" errors just
+ // because the thread doesn't wake up as soon as we want.
+ auto interval = 2s;
queue.postEvery(
interval,
[&data, count = 0]
@@ -93,7 +97,7 @@ namespace tut
data.update_one(
[](Shared& data)
{
- data.push_back(WorkQueue::TimePoint::clock::now());
+ data.push_back(WorkSchedule::TimePoint::clock::now());
});
// by the 3rd call, return false to stop
return (++count < 3);
@@ -102,7 +106,7 @@ namespace tut
// postEvery() running, so run until we have exhausted the iterations
// or we time out waiting
for (auto finish = start + 10*interval;
- WorkQueue::TimePoint::clock::now() < finish &&
+ WorkSchedule::TimePoint::clock::now() < finish &&
data.get([](const Shared& data){ return data.size(); }) < 3; )
{
queue.runPending();
@@ -139,8 +143,8 @@ namespace tut
void object::test<4>()
{
set_test_name("postTo");
- WorkQueue main("main");
- auto qptr = WorkQueue::getInstance("queue");
+ WorkSchedule main("main");
+ auto qptr = WorkSchedule::getInstance("queue");
int result = 0;
main.postTo(
qptr,
@@ -171,8 +175,8 @@ namespace tut
void object::test<5>()
{
set_test_name("postTo with void return");
- WorkQueue main("main");
- auto qptr = WorkQueue::getInstance("queue");
+ WorkSchedule main("main");
+ auto qptr = WorkSchedule::getInstance("queue");
std::string observe;
main.postTo(
qptr,
@@ -194,7 +198,7 @@ namespace tut
std::string stored;
// Try to call waitForResult() on this thread's main coroutine. It
// should throw because the main coroutine must service the queue.
- auto what{ catch_what(
+ auto what{ catch_what(
[this, &stored](){ stored = queue.waitForResult(
[](){ return "should throw"; }); }) };
ensure("lambda should not have run", stored.empty());
diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp
index d5adf11264..3a9a5a2062 100644
--- a/indra/llcommon/threadpool.cpp
+++ b/indra/llcommon/threadpool.cpp
@@ -17,18 +17,58 @@
// std headers
// external library headers
// other Linden headers
+#include "commoncontrol.h"
#include "llerror.h"
#include "llevents.h"
+#include "llsd.h"
#include "stringize.h"
-LL::ThreadPool::ThreadPool(const std::string& name, size_t threads, size_t capacity):
+#include
+
+/*****************************************************************************
+* Custom fiber scheduler for worker threads
+*****************************************************************************/
+// As of 2022-12-06, each of our worker threads only runs a single (default)
+// fiber: we don't launch explicit fibers within worker threads, nor do we
+// anticipate doing so. So a worker thread that's simply waiting for incoming
+// tasks should really sleep a little. Override the default fiber scheduler to
+// implement that.
+struct sleepy_robin: public boost::fibers::algo::round_robin
+{
+ virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept
+ {
+#if LL_WINDOWS
+ // round_robin holds a std::condition_variable, and
+ // round_robin::suspend_until() calls
+ // std::condition_variable::wait_until(). On Windows, that call seems
+ // busier than it ought to be. Try just sleeping.
+ Sleep(1);
+#else
+ // currently unused other than windows, but might as well have something here
+ // different units than Sleep(), but we actually just want to sleep for any de-minimis duration
+ usleep(1);
+#endif
+ }
+
+ virtual void notify() noexcept
+ {
+ // Since our Sleep() call above will wake up on its own, we need not
+ // take any special action to wake it.
+ }
+};
+
+/*****************************************************************************
+* ThreadPoolBase
+*****************************************************************************/
+LL::ThreadPoolBase::ThreadPoolBase(const std::string& name, size_t threads,
+ WorkQueueBase* queue):
super(name),
- mQueue(name, capacity),
mName("ThreadPool:" + name),
- mThreadCount(threads)
+ mThreadCount(getConfiguredWidth(name, threads)),
+ mQueue(queue)
{}
-void LL::ThreadPool::start()
+void LL::ThreadPoolBase::start()
{
for (size_t i = 0; i < mThreadCount; ++i)
{
@@ -56,17 +96,17 @@ void LL::ThreadPool::start()
});
}
-LL::ThreadPool::~ThreadPool()
+LL::ThreadPoolBase::~ThreadPoolBase()
{
close();
}
-void LL::ThreadPool::close()
+void LL::ThreadPoolBase::close()
{
- if (! mQueue.isClosed())
+ if (! mQueue->isClosed())
{
LL_DEBUGS("ThreadPool") << mName << " closing queue and joining threads" << LL_ENDL;
- mQueue.close();
+ mQueue->close();
for (auto& pair: mThreads)
{
LL_DEBUGS("ThreadPool") << mName << " waiting on thread " << pair.first << LL_ENDL;
@@ -76,14 +116,74 @@ void LL::ThreadPool::close()
}
}
-void LL::ThreadPool::run(const std::string& name)
+void LL::ThreadPoolBase::run(const std::string& name)
{
+#if LL_WINDOWS
+ // Try using sleepy_robin fiber scheduler.
+ boost::fibers::use_scheduling_algorithm();
+#endif // LL_WINDOWS
+
LL_DEBUGS("ThreadPool") << name << " starting" << LL_ENDL;
run();
LL_DEBUGS("ThreadPool") << name << " stopping" << LL_ENDL;
}
-void LL::ThreadPool::run()
+void LL::ThreadPoolBase::run()
{
- mQueue.runUntilClose();
+ mQueue->runUntilClose();
+}
+
+//static
+size_t LL::ThreadPoolBase::getConfiguredWidth(const std::string& name, size_t dft)
+{
+ LLSD poolSizes;
+ try
+ {
+ poolSizes = LL::CommonControl::get("Global", "ThreadPoolSizes");
+ // "ThreadPoolSizes" is actually a map containing the sizes of
+ // interest -- or should be, if this process has an
+ // LLViewerControlListener instance and its settings include
+ // "ThreadPoolSizes". If we failed to retrieve it, perhaps we're in a
+ // program that doesn't define that, or perhaps there's no such
+ // setting, or perhaps we're asking too early, before the LLEventAPI
+ // itself has been instantiated. In any of those cases, it seems worth
+ // warning.
+ if (! poolSizes.isDefined())
+ {
+ // Note: we don't warn about absence of an override key for a
+ // particular ThreadPool name, that's fine. This warning is about
+ // complete absence of a ThreadPoolSizes setting, which we expect
+ // in a normal viewer session.
+ LL_WARNS("ThreadPool") << "No 'ThreadPoolSizes' setting for ThreadPool '"
+ << name << "'" << LL_ENDL;
+ }
+ }
+ catch (const LL::CommonControl::Error& exc)
+ {
+ // We don't want ThreadPool to *require* LLViewerControlListener.
+ // Just log it and carry on.
+ LL_WARNS("ThreadPool") << "Can't check 'ThreadPoolSizes': " << exc.what() << LL_ENDL;
+ }
+
+ LL_DEBUGS("ThreadPool") << "ThreadPoolSizes = " << poolSizes << LL_ENDL;
+ // LLSD treats an undefined value as an empty map when asked to retrieve a
+ // key, so we don't need this to be conditional.
+ LLSD sizeSpec{ poolSizes[name] };
+ // We retrieve sizeSpec as LLSD, rather than immediately as LLSD::Integer,
+ // so we can distinguish the case when it's undefined.
+ return sizeSpec.isInteger() ? sizeSpec.asInteger() : dft;
+}
+
+//static
+size_t LL::ThreadPoolBase::getWidth(const std::string& name, size_t dft)
+{
+ auto instance{ getInstance(name) };
+ if (instance)
+ {
+ return instance->getWidth();
+ }
+ else
+ {
+ return getConfiguredWidth(name, dft);
+ }
}
diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h
index f8eec3b457..60f4a0ce1b 100644
--- a/indra/llcommon/threadpool.h
+++ b/indra/llcommon/threadpool.h
@@ -13,7 +13,9 @@
#if ! defined(LL_THREADPOOL_H)
#define LL_THREADPOOL_H
+#include "threadpool_fwd.h"
#include "workqueue.h"
+#include // std::unique_ptr
#include
#include
#include // std::pair
@@ -22,17 +24,24 @@
namespace LL
{
- class ThreadPool: public LLInstanceTracker
+ class ThreadPoolBase: public LLInstanceTracker
{
private:
- using super = LLInstanceTracker;
+ using super = LLInstanceTracker;
+
public:
/**
- * Pass ThreadPool a string name. This can be used to look up the
+ * Pass ThreadPoolBase a string name. This can be used to look up the
* relevant WorkQueue.
+ *
+ * The number of threads you pass sets the compile-time default. But
+ * if the user has overridden the LLSD map in the "ThreadPoolSizes"
+ * setting with a key matching this ThreadPool name, that setting
+ * overrides this parameter.
*/
- ThreadPool(const std::string& name, size_t threads=1, size_t capacity=1024);
- virtual ~ThreadPool();
+ ThreadPoolBase(const std::string& name, size_t threads,
+ WorkQueueBase* queue);
+ virtual ~ThreadPoolBase();
/**
* Launch the ThreadPool. Until this call, a constructed ThreadPool
@@ -50,8 +59,6 @@ namespace LL
std::string getName() const { return mName; }
size_t getWidth() const { return mThreads.size(); }
- /// obtain a non-const reference to the WorkQueue to post work to it
- WorkQueue& getQueue() { return mQueue; }
/**
* Override run() if you need special processing. The default run()
@@ -59,15 +66,72 @@ namespace LL
*/
virtual void run();
+ /**
+ * getConfiguredWidth() returns the setting, if any, for the specified
+ * ThreadPool name. Returns dft if the "ThreadPoolSizes" map does not
+ * contain the specified name.
+ */
+ static
+ size_t getConfiguredWidth(const std::string& name, size_t dft=0);
+
+ /**
+ * This getWidth() returns the width of the instantiated ThreadPool
+ * with the specified name, if any. If no instance exists, returns its
+ * getConfiguredWidth() if any. If there's no instance and no relevant
+ * override, return dft. Presumably dft should match the threads
+ * parameter passed to the ThreadPool constructor call that will
+ * eventually instantiate the ThreadPool with that name.
+ */
+ static
+ size_t getWidth(const std::string& name, size_t dft);
+
+ protected:
+ std::unique_ptr mQueue;
+
private:
void run(const std::string& name);
- WorkQueue mQueue;
std::string mName;
size_t mThreadCount;
std::vector> mThreads;
};
+ /**
+ * Specialize with WorkQueue or, for timestamped tasks, WorkSchedule
+ */
+ template
+ struct ThreadPoolUsing: public ThreadPoolBase
+ {
+ using queue_t = QUEUE;
+
+ /**
+ * Pass ThreadPoolUsing a string name. This can be used to look up the
+ * relevant WorkQueue.
+ *
+ * The number of threads you pass sets the compile-time default. But
+ * if the user has overridden the LLSD map in the "ThreadPoolSizes"
+ * setting with a key matching this ThreadPool name, that setting
+ * overrides this parameter.
+ *
+ * Pass an explicit capacity to limit the size of the queue.
+ * Constraining the queue can cause a submitter to block. Do not
+ * constrain any ThreadPool accepting work from the main thread.
+ */
+ ThreadPoolUsing(const std::string& name, size_t threads=1, size_t capacity=1024*1024):
+ ThreadPoolBase(name, threads, new queue_t(name, capacity))
+ {}
+ ~ThreadPoolUsing() override {}
+
+ /**
+ * obtain a non-const reference to the specific WorkQueue subclass to
+ * post work to it
+ */
+ queue_t& getQueue() { return static_cast(*mQueue); }
+ };
+
+ /// ThreadPool is shorthand for using the simpler WorkQueue
+ using ThreadPool = ThreadPoolUsing;
+
} // namespace LL
#endif /* ! defined(LL_THREADPOOL_H) */
diff --git a/indra/llcommon/threadpool_fwd.h b/indra/llcommon/threadpool_fwd.h
new file mode 100644
index 0000000000..1aa3c4a0e2
--- /dev/null
+++ b/indra/llcommon/threadpool_fwd.h
@@ -0,0 +1,25 @@
+/**
+ * @file threadpool_fwd.h
+ * @author Nat Goodspeed
+ * @date 2022-12-09
+ * @brief Forward declarations for ThreadPool et al.
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Copyright (c) 2022, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_THREADPOOL_FWD_H)
+#define LL_THREADPOOL_FWD_H
+
+#include "workqueue.h"
+
+namespace LL
+{
+ template
+ struct ThreadPoolUsing;
+
+ using ThreadPool = ThreadPoolUsing;
+} // namespace LL
+
+#endif /* ! defined(LL_THREADPOOL_FWD_H) */
diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp
index eb06890468..cf80ce0656 100644
--- a/indra/llcommon/workqueue.cpp
+++ b/indra/llcommon/workqueue.cpp
@@ -26,14 +26,121 @@
using Mutex = LLCoros::Mutex;
using Lock = LLCoros::LockType;
-LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity):
- super(makeName(name)),
- mQueue(capacity)
+/*****************************************************************************
+* WorkQueueBase
+*****************************************************************************/
+LL::WorkQueueBase::WorkQueueBase(const std::string& name):
+ super(makeName(name))
{
// TODO: register for "LLApp" events so we can implicitly close() on
// viewer shutdown.
}
+void LL::WorkQueueBase::runUntilClose()
+{
+ try
+ {
+ for (;;)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ callWork(pop_());
+ }
+ }
+ catch (const Closed&)
+ {
+ }
+}
+
+bool LL::WorkQueueBase::runPending()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ for (Work work; tryPop_(work); )
+ {
+ callWork(work);
+ }
+ return ! done();
+}
+
+bool LL::WorkQueueBase::runOne()
+{
+ Work work;
+ if (tryPop_(work))
+ {
+ callWork(work);
+ }
+ return ! done();
+}
+
+bool LL::WorkQueueBase::runUntil(const TimePoint& until)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ // Should we subtract some slop to allow for typical Work execution time?
+ // How much slop?
+ // runUntil() is simply a time-bounded runPending().
+ for (Work work; TimePoint::clock::now() < until && tryPop_(work); )
+ {
+ callWork(work);
+ }
+ return ! done();
+}
+
+std::string LL::WorkQueueBase::makeName(const std::string& name)
+{
+ if (! name.empty())
+ return name;
+
+ static U32 discriminator = 0;
+ static Mutex mutex;
+ U32 num;
+ {
+ // Protect discriminator from concurrent access by different threads.
+ // It can't be thread_local, else two racing threads will come up with
+ // the same name.
+ Lock lk(mutex);
+ num = discriminator++;
+ }
+ return STRINGIZE("WorkQueue" << num);
+}
+
+void LL::WorkQueueBase::callWork(const Work& work)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ try
+ {
+ work();
+ }
+ catch (...)
+ {
+ // No matter what goes wrong with any individual work item, the worker
+ // thread must go on! Log our own instance name with the exception.
+ LOG_UNHANDLED_EXCEPTION(getKey());
+ }
+}
+
+void LL::WorkQueueBase::error(const std::string& msg)
+{
+ LL_ERRS("WorkQueue") << msg << LL_ENDL;
+}
+
+void LL::WorkQueueBase::checkCoroutine(const std::string& method)
+{
+ // By convention, the default coroutine on each thread has an empty name
+ // string. See also LLCoros::logname().
+ if (LLCoros::getName().empty())
+ {
+ LLTHROW(Error("Do not call " + method + " from a thread's default coroutine"));
+ }
+}
+
+/*****************************************************************************
+* WorkQueue
+*****************************************************************************/
+LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity):
+ super(name),
+ mQueue(capacity)
+{
+}
+
void LL::WorkQueue::close()
{
mQueue.close();
@@ -54,105 +161,85 @@ bool LL::WorkQueue::done()
return mQueue.done();
}
-void LL::WorkQueue::runUntilClose()
+bool LL::WorkQueue::post(const Work& callable)
{
- try
- {
- for (;;)
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
- callWork(mQueue.pop());
- }
- }
- catch (const Queue::Closed&)
- {
- }
+ return mQueue.pushIfOpen(callable);
}
-bool LL::WorkQueue::runPending()
+bool LL::WorkQueue::tryPost(const Work& callable)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
- for (Work work; mQueue.tryPop(work); )
- {
- callWork(work);
- }
- return ! mQueue.done();
+ return mQueue.tryPush(callable);
}
-bool LL::WorkQueue::runOne()
+LL::WorkQueue::Work LL::WorkQueue::pop_()
{
- Work work;
- if (mQueue.tryPop(work))
- {
- callWork(work);
- }
- return ! mQueue.done();
+ return mQueue.pop();
}
-bool LL::WorkQueue::runUntil(const TimePoint& until)
+bool LL::WorkQueue::tryPop_(Work& work)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
- // Should we subtract some slop to allow for typical Work execution time?
- // How much slop?
- // runUntil() is simply a time-bounded runPending().
- for (Work work; TimePoint::clock::now() < until && mQueue.tryPop(work); )
- {
- callWork(work);
- }
- return ! mQueue.done();
+ return mQueue.tryPop(work);
}
-std::string LL::WorkQueue::makeName(const std::string& name)
+/*****************************************************************************
+* WorkSchedule
+*****************************************************************************/
+LL::WorkSchedule::WorkSchedule(const std::string& name, size_t capacity):
+ super(name),
+ mQueue(capacity)
{
- if (! name.empty())
- return name;
-
- static U32 discriminator = 0;
- static Mutex mutex;
- U32 num;
- {
- // Protect discriminator from concurrent access by different threads.
- // It can't be thread_local, else two racing threads will come up with
- // the same name.
- Lock lk(mutex);
- num = discriminator++;
- }
- return STRINGIZE("WorkQueue" << num);
}
-void LL::WorkQueue::callWork(const Queue::DataTuple& work)
+void LL::WorkSchedule::close()
{
- // ThreadSafeSchedule::pop() always delivers a tuple, even when
- // there's only one data field per item, as for us.
- callWork(std::get<0>(work));
+ mQueue.close();
}
-void LL::WorkQueue::callWork(const Work& work)
+size_t LL::WorkSchedule::size()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
- try
- {
- work();
- }
- catch (...)
- {
- // No matter what goes wrong with any individual work item, the worker
- // thread must go on! Log our own instance name with the exception.
- LOG_UNHANDLED_EXCEPTION(getKey());
- }
+ return mQueue.size();
}
-void LL::WorkQueue::error(const std::string& msg)
+bool LL::WorkSchedule::isClosed()
{
- LL_ERRS("WorkQueue") << msg << LL_ENDL;
+ return mQueue.isClosed();
}
-void LL::WorkQueue::checkCoroutine(const std::string& method)
+bool LL::WorkSchedule::done()
{
- // By convention, the default coroutine on each thread has an empty name
- // string. See also LLCoros::logname().
- if (LLCoros::getName().empty())
- {
- LLTHROW(Error("Do not call " + method + " from a thread's default coroutine"));
- }
+ return mQueue.done();
+}
+
+bool LL::WorkSchedule::post(const Work& callable)
+{
+ // Use TimePoint::clock::now() instead of TimePoint's representation of
+ // the epoch because this WorkSchedule may contain a mix of past-due
+ // TimedWork items and TimedWork items scheduled for the future. Sift this
+ // new item into the correct place.
+ return post(callable, TimePoint::clock::now());
+}
+
+bool LL::WorkSchedule::post(const Work& callable, const TimePoint& time)
+{
+ return mQueue.pushIfOpen(TimedWork(time, callable));
+}
+
+bool LL::WorkSchedule::tryPost(const Work& callable)
+{
+ return tryPost(callable, TimePoint::clock::now());
+}
+
+bool LL::WorkSchedule::tryPost(const Work& callable, const TimePoint& time)
+{
+ return mQueue.tryPush(TimedWork(time, callable));
+}
+
+LL::WorkSchedule::Work LL::WorkSchedule::pop_()
+{
+ return std::get<0>(mQueue.pop());
+}
+
+bool LL::WorkSchedule::tryPop_(Work& work)
+{
+ return mQueue.tryPop(work);
}
diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h
index 70fd65bd0c..ec0700a718 100644
--- a/indra/llcommon/workqueue.h
+++ b/indra/llcommon/workqueue.h
@@ -15,6 +15,7 @@
#include "llcoros.h"
#include "llexception.h"
#include "llinstancetracker.h"
+#include "llinstancetrackersubclass.h"
#include "threadsafeschedule.h"
#include
#include // std::current_exception
@@ -23,27 +24,23 @@
namespace LL
{
+
+/*****************************************************************************
+* WorkQueueBase: API for WorkQueue and WorkSchedule
+*****************************************************************************/
/**
* A typical WorkQueue has a string name that can be used to find it.
*/
- class WorkQueue: public LLInstanceTracker
+ class WorkQueueBase: public LLInstanceTracker
{
private:
- using super = LLInstanceTracker;
+ using super = LLInstanceTracker;
public:
using Work = std::function;
-
- private:
- using Queue = ThreadSafeSchedule;
- // helper for postEvery()
- template
- class BackJack;
-
- public:
- using TimePoint = Queue::TimePoint;
- using TimedWork = Queue::TimeTuple;
- using Closed = Queue::Closed;
+ using Closed = LLThreadSafeQueueInterrupt;
+ // for runFor()
+ using TimePoint = std::chrono::steady_clock::time_point;
struct Error: public LLException
{
@@ -51,18 +48,18 @@ namespace LL
};
/**
- * You may omit the WorkQueue name, in which case a unique name is
+ * You may omit the WorkQueueBase name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous.
*/
- WorkQueue(const std::string& name = std::string(), size_t capacity=1024);
+ WorkQueueBase(const std::string& name);
/**
* Since the point of WorkQueue is to pass work to some other worker
- * thread(s) asynchronously, it's important that the WorkQueue continue
- * to exist until the worker thread(s) have drained it. To communicate
- * that it's time for them to quit, close() the queue.
+ * thread(s) asynchronously, it's important that it continue to exist
+ * until the worker thread(s) have drained it. To communicate that
+ * it's time for them to quit, close() the queue.
*/
- void close();
+ virtual void close() = 0;
/**
* WorkQueue supports multiple producers and multiple consumers. In
@@ -78,152 +75,57 @@ namespace LL
* * If you're the only consumer, noticing that size() > 0 is
* meaningful.
*/
- size_t size();
+ virtual size_t size() = 0;
/// producer end: are we prevented from pushing any additional items?
- bool isClosed();
+ virtual bool isClosed() = 0;
/// consumer end: are we done, is the queue entirely drained?
- bool done();
+ virtual bool done() = 0;
/*---------------------- fire and forget API -----------------------*/
- /// fire-and-forget, but at a particular (future?) time
- template
- void post(const TimePoint& time, CALLABLE&& callable)
- {
- // Defer reifying an arbitrary CALLABLE until we hit this or
- // postIfOpen(). All other methods should accept CALLABLEs of
- // arbitrary type to avoid multiple levels of std::function
- // indirection.
- mQueue.push(TimedWork(time, std::move(callable)));
- }
-
- /// fire-and-forget
- template
- void post(CALLABLE&& callable)
- {
- // We use TimePoint::clock::now() instead of TimePoint's
- // representation of the epoch because this WorkQueue may contain
- // a mix of past-due TimedWork items and TimedWork items scheduled
- // for the future. Sift this new item into the correct place.
- post(TimePoint::clock::now(), std::move(callable));
- }
-
- /**
- * post work for a particular time, unless the queue is closed before
- * we can post
- */
- template
- bool postIfOpen(const TimePoint& time, CALLABLE&& callable)
- {
- // Defer reifying an arbitrary CALLABLE until we hit this or
- // post(). All other methods should accept CALLABLEs of arbitrary
- // type to avoid multiple levels of std::function indirection.
- return mQueue.pushIfOpen(TimedWork(time, std::move(callable)));
- }
-
/**
* post work, unless the queue is closed before we can post
*/
- template
- bool postIfOpen(CALLABLE&& callable)
- {
- return postIfOpen(TimePoint::clock::now(), std::move(callable));
- }
+ virtual bool post(const Work&) = 0;
/**
- * Post work to be run at a specified time to another WorkQueue, which
- * may or may not still exist and be open. Return true if we were able
- * to post.
+ * post work, unless the queue is full
*/
- template
- static bool postMaybe(weak_t target, const TimePoint& time, CALLABLE&& callable);
+ virtual bool tryPost(const Work&) = 0;
/**
* Post work to another WorkQueue, which may or may not still exist
- * and be open. Return true if we were able to post.
+ * and be open. Support any post() overload. Return true if we were
+ * able to post.
*/
- template
- static bool postMaybe(weak_t target, CALLABLE&& callable)
- {
- return postMaybe(target, TimePoint::clock::now(),
- std::forward(callable));
- }
-
- /**
- * Launch a callable returning bool that will trigger repeatedly at
- * specified interval, until the callable returns false.
- *
- * If you need to signal that callable from outside, DO NOT bind a
- * reference to a simple bool! That's not thread-safe. Instead, bind
- * an LLCond variant, e.g. LLOneShotCond or LLBoolCond.
- */
- template
- void postEvery(const std::chrono::duration& interval,
- CALLABLE&& callable);
-
- template
- bool tryPost(CALLABLE&& callable)
- {
- return mQueue.tryPush(TimedWork(TimePoint::clock::now(), std::move(callable)));
- }
+ template
+ static bool postMaybe(weak_t target, ARGS&&... args);
/*------------------------- handshake API --------------------------*/
- /**
- * Post work to another WorkQueue to be run at a specified time,
- * requesting a specific callback to be run on this WorkQueue on
- * completion.
- *
- * Returns true if able to post, false if the other WorkQueue is
- * inaccessible.
- */
- // Apparently some Microsoft header file defines a macro CALLBACK? The
- // natural template argument name CALLBACK produces very weird Visual
- // Studio compile errors that seem utterly unrelated to this source
- // code.
- template
- bool postTo(weak_t target,
- const TimePoint& time, CALLABLE&& callable, FOLLOWUP&& callback);
-
/**
* Post work to another WorkQueue, requesting a specific callback to
- * be run on this WorkQueue on completion.
+ * be run on this WorkQueue on completion. Optional final argument is
+ * TimePoint for WorkSchedule.
*
* Returns true if able to post, false if the other WorkQueue is
* inaccessible.
*/
- template
- bool postTo(weak_t target, CALLABLE&& callable, FOLLOWUP&& callback)
- {
- return postTo(target, TimePoint::clock::now(),
- std::move(callable), std::move(callback));
- }
-
- /**
- * Post work to another WorkQueue to be run at a specified time,
- * blocking the calling coroutine until then, returning the result to
- * caller on completion.
- *
- * In general, we assume that each thread's default coroutine is busy
- * servicing its WorkQueue or whatever. To try to prevent mistakes, we
- * forbid calling waitForResult() from a thread's default coroutine.
- */
- template
- auto waitForResult(const TimePoint& time, CALLABLE&& callable);
+ template
+ bool postTo(weak_t target, CALLABLE&& callable, FOLLOWUP&& callback,
+ ARGS&&... args);
/**
* Post work to another WorkQueue, blocking the calling coroutine
- * until then, returning the result to caller on completion.
+ * until then, returning the result to caller on completion. Optional
+ * final argument is TimePoint for WorkSchedule.
*
* In general, we assume that each thread's default coroutine is busy
* servicing its WorkQueue or whatever. To try to prevent mistakes, we
* forbid calling waitForResult() from a thread's default coroutine.
*/
- template
- auto waitForResult(CALLABLE&& callable)
- {
- return waitForResult(TimePoint::clock::now(), std::move(callable));
- }
+ template
+ auto waitForResult(CALLABLE&& callable, ARGS&&... args);
/*--------------------------- worker API ---------------------------*/
@@ -270,7 +172,7 @@ namespace LL
*/
bool runUntil(const TimePoint& until);
- private:
+ protected:
template
static auto makeReplyLambda(CALLABLE&& callable, FOLLOWUP&& callback);
/// general case: arbitrary C++ return type
@@ -290,13 +192,170 @@ namespace LL
static void checkCoroutine(const std::string& method);
static void error(const std::string& msg);
static std::string makeName(const std::string& name);
- void callWork(const Queue::DataTuple& work);
void callWork(const Work& work);
+
+ private:
+ virtual Work pop_() = 0;
+ virtual bool tryPop_(Work&) = 0;
+ };
+
+/*****************************************************************************
+* WorkQueue: no timestamped task support
+*****************************************************************************/
+ class WorkQueue: public LLInstanceTrackerSubclass
+ {
+ private:
+ using super = LLInstanceTrackerSubclass;
+
+ public:
+ /**
+ * You may omit the WorkQueue name, in which case a unique name is
+ * synthesized; for practical purposes that makes it anonymous.
+ */
+ WorkQueue(const std::string& name = std::string(), size_t capacity=1024);
+
+ /**
+ * Since the point of WorkQueue is to pass work to some other worker
+ * thread(s) asynchronously, it's important that it continue to exist
+ * until the worker thread(s) have drained it. To communicate that
+ * it's time for them to quit, close() the queue.
+ */
+ void close() override;
+
+ /**
+ * WorkQueue supports multiple producers and multiple consumers. In
+ * the general case it's misleading to test size(), since any other
+ * thread might change it the nanosecond the lock is released. On that
+ * basis, some might argue against publishing a size() method at all.
+ *
+ * But there are two specific cases in which a test based on size()
+ * might be reasonable:
+ *
+ * * If you're the only producer, noticing that size() == 0 is
+ * meaningful.
+ * * If you're the only consumer, noticing that size() > 0 is
+ * meaningful.
+ */
+ size_t size() override;
+ /// producer end: are we prevented from pushing any additional items?
+ bool isClosed() override;
+ /// consumer end: are we done, is the queue entirely drained?
+ bool done() override;
+
+ /*---------------------- fire and forget API -----------------------*/
+
+ /**
+ * post work, unless the queue is closed before we can post
+ */
+ bool post(const Work&) override;
+
+ /**
+ * post work, unless the queue is full
+ */
+ bool tryPost(const Work&) override;
+
+ private:
+ using Queue = LLThreadSafeQueue;
Queue mQueue;
+
+ Work pop_() override;
+ bool tryPop_(Work&) override;
+ };
+
+/*****************************************************************************
+* WorkSchedule: add support for timestamped tasks
+*****************************************************************************/
+ class WorkSchedule: public LLInstanceTrackerSubclass
+ {
+ private:
+ using super = LLInstanceTrackerSubclass;
+ using Queue = ThreadSafeSchedule;
+ // helper for postEvery()
+ template
+ class BackJack;
+
+ public:
+ using TimePoint = Queue::TimePoint;
+ using TimedWork = Queue::TimeTuple;
+
+ /**
+ * You may omit the WorkSchedule name, in which case a unique name is
+ * synthesized; for practical purposes that makes it anonymous.
+ */
+ WorkSchedule(const std::string& name = std::string(), size_t capacity=1024);
+
+ /**
+ * Since the point of WorkSchedule is to pass work to some other worker
+ * thread(s) asynchronously, it's important that the WorkSchedule continue
+ * to exist until the worker thread(s) have drained it. To communicate
+ * that it's time for them to quit, close() the queue.
+ */
+ void close() override;
+
+ /**
+ * WorkSchedule supports multiple producers and multiple consumers. In
+ * the general case it's misleading to test size(), since any other
+ * thread might change it the nanosecond the lock is released. On that
+ * basis, some might argue against publishing a size() method at all.
+ *
+ * But there are two specific cases in which a test based on size()
+ * might be reasonable:
+ *
+ * * If you're the only producer, noticing that size() == 0 is
+ * meaningful.
+ * * If you're the only consumer, noticing that size() > 0 is
+ * meaningful.
+ */
+ size_t size() override;
+ /// producer end: are we prevented from pushing any additional items?
+ bool isClosed() override;
+ /// consumer end: are we done, is the queue entirely drained?
+ bool done() override;
+
+ /*---------------------- fire and forget API -----------------------*/
+
+ /**
+ * post work, unless the queue is closed before we can post
+ */
+ bool post(const Work& callable) override;
+
+ /**
+ * post work for a particular time, unless the queue is closed before
+ * we can post
+ */
+ bool post(const Work& callable, const TimePoint& time);
+
+ /**
+ * post work, unless the queue is full
+ */
+ bool tryPost(const Work& callable) override;
+
+ /**
+ * post work for a particular time, unless the queue is full
+ */
+ bool tryPost(const Work& callable, const TimePoint& time);
+
+ /**
+ * Launch a callable returning bool that will trigger repeatedly at
+ * specified interval, until the callable returns false.
+ *
+ * If you need to signal that callable from outside, DO NOT bind a
+ * reference to a simple bool! That's not thread-safe. Instead, bind
+ * an LLCond variant, e.g. LLOneShotCond or LLBoolCond.
+ */
+ template
+ bool postEvery(const std::chrono::duration& interval,
+ CALLABLE&& callable);
+
+ private:
+ Queue mQueue;
+
+ Work pop_() override;
+ bool tryPop_(Work&) override;
};
/**
- * BackJack is, in effect, a hand-rolled lambda, binding a WorkQueue, a
+ * BackJack is, in effect, a hand-rolled lambda, binding a WorkSchedule, a
* CALLABLE that returns bool, a TimePoint and an interval at which to
* relaunch it. As long as the callable continues returning true, BackJack
* keeps resubmitting it to the target WorkQueue.
@@ -305,7 +364,7 @@ namespace LL
// class method gets its own 'this' pointer -- which we need to resubmit
// the whole BackJack callable.
template
- class WorkQueue::BackJack
+ class WorkSchedule::BackJack
{
public:
// bind the desired data
@@ -319,9 +378,10 @@ namespace LL
mCallable(std::move(callable))
{}
- // Call by target WorkQueue -- note that although WE require a
- // callable returning bool, WorkQueue wants a void callable. We
- // consume the bool.
+ // This operator() method, called by target WorkSchedule, is what
+ // makes this object a Work item. Although WE require a callable
+ // returning bool, WorkSchedule wants a void callable. We consume the
+ // bool.
void operator()()
{
// If mCallable() throws an exception, don't catch it here: if it
@@ -337,7 +397,7 @@ namespace LL
// register our intent to fire at exact mIntervals.
mStart += mInterval;
- // We're being called at this moment by the target WorkQueue.
+ // We're being called at this moment by the target WorkSchedule.
// Assume it still exists, rather than checking the result of
// lock().
// Resubmit the whole *this callable: that's why we're a class
@@ -345,14 +405,10 @@ namespace LL
// move-only callable; but naturally this statement must be
// the last time we reference this instance, which may become
// moved-from.
- try
- {
- mTarget.lock()->post(mStart, std::move(*this));
- }
- catch (const Closed&)
- {
- // Once this queue is closed, oh well, just stop
- }
+ auto target{ std::dynamic_pointer_cast(mTarget.lock()) };
+ // Discard bool return: once this queue is closed, oh well,
+ // just stop
+ target->post(std::move(*this), mStart);
}
}
@@ -364,8 +420,8 @@ namespace LL
};
template
- void WorkQueue::postEvery(const std::chrono::duration& interval,
- CALLABLE&& callable)
+ bool WorkSchedule::postEvery(const std::chrono::duration& interval,
+ CALLABLE&& callable)
{
if (interval.count() <= 0)
{
@@ -381,14 +437,14 @@ namespace LL
// Instantiate and post a suitable BackJack, binding a weak_ptr to
// self, the current time, the desired interval and the desired
// callable.
- post(
+ return post(
BackJack(
getWeak(), TimePoint::clock::now(), interval, std::move(callable)));
}
/// general case: arbitrary C++ return type
template
- struct WorkQueue::MakeReplyLambda
+ struct WorkQueueBase::MakeReplyLambda
{
auto operator()(CALLABLE&& callable, FOLLOWUP&& callback)
{
@@ -409,7 +465,7 @@ namespace LL
/// specialize for CALLABLE returning void
template
- struct WorkQueue::MakeReplyLambda
+ struct WorkQueueBase::MakeReplyLambda
{
auto operator()(CALLABLE&& callable, FOLLOWUP&& callback)
{
@@ -421,16 +477,16 @@ namespace LL
};
template
- auto WorkQueue::makeReplyLambda(CALLABLE&& callable, FOLLOWUP&& callback)
+ auto WorkQueueBase::makeReplyLambda(CALLABLE&& callable, FOLLOWUP&& callback)
{
return MakeReplyLambda(callable)())>()
(std::move(callable), std::move(callback));
}
- template
- bool WorkQueue::postTo(weak_t target,
- const TimePoint& time, CALLABLE&& callable, FOLLOWUP&& callback)
+ template
+ bool WorkQueueBase::postTo(weak_t target, CALLABLE&& callable, FOLLOWUP&& callback,
+ ARGS&&... args)
{
LL_PROFILE_ZONE_SCOPED;
// We're being asked to post to the WorkQueue at target.
@@ -443,13 +499,12 @@ namespace LL
// Here we believe target WorkQueue still exists. Post to it a
// lambda that packages our callable, our callback and a weak_ptr
// to this originating WorkQueue.
- tptr->post(
- time,
+ return tptr->post(
[reply = super::getWeak(),
callable = std::move(callable),
callback = std::move(callback)]
- ()
- mutable {
+ () mutable
+ {
// Use postMaybe() below in case this originating WorkQueue
// has been closed or destroyed. Remember, the outer lambda is
// now running on a thread servicing the target WorkQueue, and
@@ -472,44 +527,34 @@ namespace LL
// originating WorkQueue. Once there, rethrow it.
[exc = std::current_exception()](){ std::rethrow_exception(exc); });
}
- });
-
- // looks like we were able to post()
- return true;
+ },
+ // if caller passed a TimePoint, pass it along to post()
+ std::forward(args)...);
}
- template
- bool WorkQueue::postMaybe(weak_t target, const TimePoint& time, CALLABLE&& callable)
+ template
+ bool WorkQueueBase::postMaybe(weak_t target, ARGS&&... args)
{
LL_PROFILE_ZONE_SCOPED;
// target is a weak_ptr: have to lock it to check it
auto tptr = target.lock();
if (tptr)
{
- try
- {
- tptr->post(time, std::forward(callable));
- // we were able to post()
- return true;
- }
- catch (const Closed&)
- {
- // target WorkQueue still exists, but is Closed
- }
+ return tptr->post(std::forward(args)...);
}
- // either target no longer exists, or its WorkQueue is Closed
+ // target no longer exists
return false;
}
/// general case: arbitrary C++ return type
template
- struct WorkQueue::WaitForResult
+ struct WorkQueueBase::WaitForResult
{
- auto operator()(WorkQueue* self, const TimePoint& time, CALLABLE&& callable)
+ template
+ auto operator()(WorkQueueBase* self, CALLABLE&& callable, ARGS&&... args)
{
LLCoros::Promise promise;
- self->post(
- time,
+ bool posted = self->post(
// We dare to bind a reference to Promise because it's
// specifically designed for cross-thread communication.
[&promise, callable = std::move(callable)]()
@@ -523,7 +568,13 @@ namespace LL
{
promise.set_exception(std::current_exception());
}
- });
+ },
+ // if caller passed a TimePoint, pass it to post()
+ std::forward(args)...);
+ if (! posted)
+ {
+ LLTHROW(WorkQueueBase::Closed());
+ }
auto future{ LLCoros::getFuture(promise) };
// now, on the calling thread, wait for that result
LLCoros::TempStatus st("waiting for WorkQueue::waitForResult()");
@@ -533,13 +584,13 @@ namespace LL
/// specialize for CALLABLE returning void
template
- struct WorkQueue::WaitForResult
+ struct WorkQueueBase::WaitForResult
{
- void operator()(WorkQueue* self, const TimePoint& time, CALLABLE&& callable)
+ template
+ void operator()(WorkQueueBase* self, CALLABLE&& callable, ARGS&&... args)
{
LLCoros::Promise promise;
- self->post(
- time,
+ bool posted = self->post(
// &promise is designed for cross-thread access
[&promise, callable = std::move(callable)]()
mutable {
@@ -552,7 +603,13 @@ namespace LL
{
promise.set_exception(std::current_exception());
}
- });
+ },
+ // if caller passed a TimePoint, pass it to post()
+ std::forward(args)...);
+ if (! posted)
+ {
+ LLTHROW(WorkQueueBase::Closed());
+ }
auto future{ LLCoros::getFuture(promise) };
// block until set_value()
LLCoros::TempStatus st("waiting for void WorkQueue::waitForResult()");
@@ -560,13 +617,13 @@ namespace LL
}
};
- template
- auto WorkQueue::waitForResult(const TimePoint& time, CALLABLE&& callable)
+ template
+ auto WorkQueueBase::waitForResult(CALLABLE&& callable, ARGS&&... args)
{
checkCoroutine("waitForResult()");
// derive callable's return type so we can specialize for void
return WaitForResult(callable)())>()
- (this, time, std::forward(callable));
+ (this, std::forward(callable), std::forward(args)...);
}
} // namespace LL
diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index 975ce8a4d5..bd0ac740db 100644
--- a/indra/llcorehttp/_httplibcurl.cpp
+++ b/indra/llcorehttp/_httplibcurl.cpp
@@ -113,6 +113,7 @@ void HttpLibcurl::shutdown()
void HttpLibcurl::start(int policy_count)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
llassert_always(policy_count <= HTTP_POLICY_CLASS_LIMIT);
llassert_always(! mMultiHandles); // One-time call only
@@ -143,6 +144,7 @@ void HttpLibcurl::start(int policy_count)
// sleep otherwise ask for a normal polling interval.
HttpService::ELoopSpeed HttpLibcurl::processTransport()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpService::ELoopSpeed ret(HttpService::REQUEST_SLEEP);
// Give libcurl some cycles to do I/O & callbacks
@@ -168,6 +170,7 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()
CURLMcode status(CURLM_CALL_MULTI_PERFORM);
do
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("httppt - curl_multi_perform");
running = 0;
status = curl_multi_perform(mMultiHandles[policy_class], &running);
}
@@ -176,31 +179,34 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()
// Run completion on anything done
CURLMsg * msg(NULL);
int msgs_in_queue(0);
- while ((msg = curl_multi_info_read(mMultiHandles[policy_class], &msgs_in_queue)))
- {
- if (CURLMSG_DONE == msg->msg)
- {
- CURL * handle(msg->easy_handle);
- CURLcode result(msg->data.result);
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("httppt - curl_multi_info_read");
+ while ((msg = curl_multi_info_read(mMultiHandles[policy_class], &msgs_in_queue)))
+ {
+ if (CURLMSG_DONE == msg->msg)
+ {
+ CURL* handle(msg->easy_handle);
+ CURLcode result(msg->data.result);
- completeRequest(mMultiHandles[policy_class], handle, result);
- handle = NULL; // No longer valid on return
- ret = HttpService::NORMAL; // If anything completes, we may have a free slot.
- // Turning around quickly reduces connection gap by 7-10mS.
- }
- else if (CURLMSG_NONE == msg->msg)
- {
- // Ignore this... it shouldn't mean anything.
- ;
- }
- else
- {
- LL_WARNS_ONCE(LOG_CORE) << "Unexpected message from libcurl. Msg code: "
- << msg->msg
- << LL_ENDL;
- }
- msgs_in_queue = 0;
- }
+ completeRequest(mMultiHandles[policy_class], handle, result);
+ handle = NULL; // No longer valid on return
+ ret = HttpService::NORMAL; // If anything completes, we may have a free slot.
+ // Turning around quickly reduces connection gap by 7-10mS.
+ }
+ else if (CURLMSG_NONE == msg->msg)
+ {
+ // Ignore this... it shouldn't mean anything.
+ ;
+ }
+ else
+ {
+ LL_WARNS_ONCE(LOG_CORE) << "Unexpected message from libcurl. Msg code: "
+ << msg->msg
+ << LL_ENDL;
+ }
+ msgs_in_queue = 0;
+ }
+ }
}
if (! mActiveOps.empty())
@@ -214,6 +220,7 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()
// Caller has provided us with a ref count on op.
void HttpLibcurl::addOp(const HttpOpRequest::ptr_t &op)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
llassert_always(op->mReqPolicy < mPolicyCount);
llassert_always(mMultiHandles[op->mReqPolicy] != NULL);
@@ -257,6 +264,7 @@ void HttpLibcurl::addOp(const HttpOpRequest::ptr_t &op)
// method to kill the request.
bool HttpLibcurl::cancel(HttpHandle handle)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op = HttpOpRequest::fromHandle(handle);
active_set_t::iterator it(mActiveOps.find(op));
if (mActiveOps.end() == it)
@@ -282,6 +290,7 @@ bool HttpLibcurl::cancel(HttpHandle handle)
// op to the reply queue with refcount intact.
void HttpLibcurl::cancelRequest(const HttpOpRequest::ptr_t &op)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
// Deactivate request
op->mCurlActive = false;
@@ -308,6 +317,7 @@ void HttpLibcurl::cancelRequest(const HttpOpRequest::ptr_t &op)
// Keep them synchronized as necessary.
bool HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode status)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpHandle ophandle(NULL);
CURLcode ccode(CURLE_OK);
@@ -445,6 +455,7 @@ int HttpLibcurl::getActiveCountInClass(int policy_class) const
void HttpLibcurl::policyUpdated(int policy_class)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
if (policy_class < 0 || policy_class >= mPolicyCount || ! mMultiHandles)
{
return;
diff --git a/indra/llcorehttp/_httpoperation.cpp b/indra/llcorehttp/_httpoperation.cpp
index 3fc4e28910..3b64018132 100644
--- a/indra/llcorehttp/_httpoperation.cpp
+++ b/indra/llcorehttp/_httpoperation.cpp
@@ -62,7 +62,6 @@ HttpOperation::HttpOperation():
mReplyQueue(),
mUserHandler(),
mReqPolicy(HttpRequest::DEFAULT_POLICY_ID),
- mReqPriority(0U),
mTracing(HTTP_TRACE_OFF),
mMyHandle(LLCORE_HTTP_HANDLE_INVALID)
{
diff --git a/indra/llcorehttp/_httpoperation.h b/indra/llcorehttp/_httpoperation.h
index 1a75921c09..8c1364bab4 100644
--- a/indra/llcorehttp/_httpoperation.h
+++ b/indra/llcorehttp/_httpoperation.h
@@ -181,7 +181,6 @@ protected:
public:
// Request Data
HttpRequest::policy_t mReqPolicy;
- HttpRequest::priority_t mReqPriority;
// Reply Data
HttpStatus mStatus;
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index ba31290c24..d60eb6c95f 100644
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -200,6 +200,7 @@ HttpOpRequest::~HttpOpRequest()
void HttpOpRequest::stageFromRequest(HttpService * service)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t self(boost::dynamic_pointer_cast(shared_from_this()));
service->getPolicy().addOp(self); // transfers refcount
}
@@ -207,6 +208,7 @@ void HttpOpRequest::stageFromRequest(HttpService * service)
void HttpOpRequest::stageFromReady(HttpService * service)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t self(boost::dynamic_pointer_cast(shared_from_this()));
service->getTransport().addOp(self); // transfers refcount
}
@@ -214,6 +216,7 @@ void HttpOpRequest::stageFromReady(HttpService * service)
void HttpOpRequest::stageFromActive(HttpService * service)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
if (mReplyLength)
{
// If non-zero, we received and processed a Content-Range
@@ -250,6 +253,7 @@ void HttpOpRequest::stageFromActive(HttpService * service)
void HttpOpRequest::visitNotifier(HttpRequest * request)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
if (mUserHandler)
{
HttpResponse * response = new HttpResponse();
@@ -292,6 +296,7 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
HttpStatus HttpOpRequest::cancel()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
mStatus = HttpStatus(HttpStatus::LLCORE, HE_OP_CANCELED);
addAsReply();
@@ -301,12 +306,12 @@ HttpStatus HttpOpRequest::cancel()
HttpStatus HttpOpRequest::setupGet(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
- setupCommon(policy_id, priority, url, NULL, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, NULL, options, headers);
mReqMethod = HOR_GET;
return HttpStatus();
@@ -314,14 +319,14 @@ HttpStatus HttpOpRequest::setupGet(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupGetByteRange(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
size_t offset,
size_t len,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
- setupCommon(policy_id, priority, url, NULL, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, NULL, options, headers);
mReqMethod = HOR_GET;
mReqOffset = offset;
mReqLength = len;
@@ -335,13 +340,13 @@ HttpStatus HttpOpRequest::setupGetByteRange(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupPost(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
- setupCommon(policy_id, priority, url, body, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, body, options, headers);
mReqMethod = HOR_POST;
return HttpStatus();
@@ -349,13 +354,13 @@ HttpStatus HttpOpRequest::setupPost(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
- setupCommon(policy_id, priority, url, body, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, body, options, headers);
mReqMethod = HOR_PUT;
return HttpStatus();
@@ -363,12 +368,12 @@ HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupDelete(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
- setupCommon(policy_id, priority, url, NULL, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, NULL, options, headers);
mReqMethod = HOR_DELETE;
return HttpStatus();
@@ -376,13 +381,13 @@ HttpStatus HttpOpRequest::setupDelete(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupPatch(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
- setupCommon(policy_id, priority, url, body, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, body, options, headers);
mReqMethod = HOR_PATCH;
return HttpStatus();
@@ -390,12 +395,12 @@ HttpStatus HttpOpRequest::setupPatch(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupCopy(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t &headers)
{
- setupCommon(policy_id, priority, url, NULL, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, NULL, options, headers);
mReqMethod = HOR_COPY;
return HttpStatus();
@@ -403,12 +408,12 @@ HttpStatus HttpOpRequest::setupCopy(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupMove(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t &headers)
{
- setupCommon(policy_id, priority, url, NULL, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, NULL, options, headers);
mReqMethod = HOR_MOVE;
return HttpStatus();
@@ -416,15 +421,14 @@ HttpStatus HttpOpRequest::setupMove(HttpRequest::policy_t policy_id,
void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
mProcFlags = 0U;
mReqPolicy = policy_id;
- mReqPriority = priority;
mReqURL = url;
if (body)
{
@@ -465,6 +469,7 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,
// *TODO: Move this to _httplibcurl where it belongs.
HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
// Scrub transport and result data for retried op case
mCurlActive = false;
mCurlHandle = NULL;
@@ -773,6 +778,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void * userdata)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle(userdata));
if (! op->mReplyBody)
@@ -788,6 +794,7 @@ size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void
size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void * userdata)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle(userdata));
if (! op->mReqBody)
@@ -819,6 +826,7 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void
int HttpOpRequest::seekCallback(void *userdata, curl_off_t offset, int origin)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle(userdata));
if (!op->mReqBody)
@@ -850,6 +858,7 @@ int HttpOpRequest::seekCallback(void *userdata, curl_off_t offset, int origin)
size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, void * userdata)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
static const char status_line[] = "HTTP/";
static const size_t status_line_len = sizeof(status_line) - 1;
static const char con_ran_line[] = "content-range";
@@ -999,6 +1008,7 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
CURLcode HttpOpRequest::curlSslCtxCallback(CURL *curl, void *sslctx, void *userdata)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle(userdata));
if (op->mCallbackSSLVerify)
@@ -1025,6 +1035,7 @@ CURLcode HttpOpRequest::curlSslCtxCallback(CURL *curl, void *sslctx, void *userd
int HttpOpRequest::sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle(param));
if (op->mCallbackSSLVerify)
@@ -1037,6 +1048,7 @@ int HttpOpRequest::sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param)
int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffer, size_t len, void * userdata)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle(userdata));
std::string safe_line;
diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h
index cdbe350785..ec84822cf4 100644
--- a/indra/llcorehttp/_httpoprequest.h
+++ b/indra/llcorehttp/_httpoprequest.h
@@ -105,13 +105,11 @@ public:
/// Threading: called by application thread
///
HttpStatus setupGet(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
HttpStatus setupGetByteRange(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
size_t offset,
size_t len,
@@ -119,40 +117,34 @@ public:
const HttpHeaders::ptr_t & headers);
HttpStatus setupPost(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
HttpStatus setupPut(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
HttpStatus setupDelete(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
HttpStatus setupPatch(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
HttpStatus setupCopy(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
HttpStatus setupMove(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
@@ -172,7 +164,6 @@ protected:
// Threading: called by application thread
//
void setupCommon(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -239,19 +230,6 @@ public:
-/// HttpOpRequestCompare isn't an operation but a uniform comparison
-/// functor for STL containers that order by priority. Mainly
-/// used for the ready queue container but defined here.
-class HttpOpRequestCompare
-{
-public:
- bool operator()(const HttpOpRequest * lhs, const HttpOpRequest * rhs)
- {
- return lhs->mReqPriority > rhs->mReqPriority;
- }
-}; // end class HttpOpRequestCompare
-
-
// ---------------------------------------
// Free functions
// ---------------------------------------
diff --git a/indra/llcorehttp/_httpopsetpriority.cpp b/indra/llcorehttp/_httpopsetpriority.cpp
index d48c7a0b7d..b99b4e9e4a 100644
--- a/indra/llcorehttp/_httpopsetpriority.cpp
+++ b/indra/llcorehttp/_httpopsetpriority.cpp
@@ -24,6 +24,7 @@
* $/LicenseInfo$
*/
+#if 0 // DEPRECATED
#include "_httpopsetpriority.h"
#include "httpresponse.h"
@@ -61,3 +62,5 @@ void HttpOpSetPriority::stageFromRequest(HttpService * service)
} // end namespace LLCore
+
+#endif
diff --git a/indra/llcorehttp/_httpopsetpriority.h b/indra/llcorehttp/_httpopsetpriority.h
index 43e2aa081b..fd543f37cc 100644
--- a/indra/llcorehttp/_httpopsetpriority.h
+++ b/indra/llcorehttp/_httpopsetpriority.h
@@ -27,7 +27,7 @@
#ifndef _LLCORE_HTTP_SETPRIORITY_H_
#define _LLCORE_HTTP_SETPRIORITY_H_
-
+#if 0 // DEPRECATED
#include "httpcommon.h"
#include "httprequest.h"
#include "_httpoperation.h"
@@ -49,7 +49,7 @@ namespace LLCore
class HttpOpSetPriority : public HttpOperation
{
public:
- HttpOpSetPriority(HttpHandle handle, HttpRequest::priority_t priority);
+ HttpOpSetPriority(HttpHandle handle);
virtual ~HttpOpSetPriority();
@@ -63,10 +63,10 @@ public:
protected:
// Request Data
HttpHandle mHandle;
- HttpRequest::priority_t mPriority;
}; // end class HttpOpSetPriority
} // end namespace LLCore
+#endif
#endif // _LLCORE_HTTP_SETPRIORITY_H_
diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp
index 885f0ed61d..29f50c1693 100644
--- a/indra/llcorehttp/_httppolicy.cpp
+++ b/indra/llcorehttp/_httppolicy.cpp
@@ -330,37 +330,6 @@ HttpService::ELoopSpeed HttpPolicy::processReadyQueue()
return result;
}
-
-bool HttpPolicy::changePriority(HttpHandle handle, HttpRequest::priority_t priority)
-{
- for (int policy_class(0); policy_class < mClasses.size(); ++policy_class)
- {
- ClassState & state(*mClasses[policy_class]);
- // We don't scan retry queue because a priority change there
- // is meaningless. The request will be issued based on retry
- // intervals not priority value, which is now moot.
-
- // Scan ready queue for requests that match policy
- HttpReadyQueue::container_type & c(state.mReadyQueue.get_container());
- for (HttpReadyQueue::container_type::iterator iter(c.begin()); c.end() != iter;)
- {
- HttpReadyQueue::container_type::iterator cur(iter++);
-
- if ((*cur)->getHandle() == handle)
- {
- HttpOpRequest::ptr_t op(*cur);
- c.erase(cur); // All iterators are now invalidated
- op->mReqPriority = priority;
- state.mReadyQueue.push(op); // Re-insert using adapter class
- return true;
- }
- }
- }
-
- return false;
-}
-
-
bool HttpPolicy::cancel(HttpHandle handle)
{
for (int policy_class(0); policy_class < mClasses.size(); ++policy_class)
diff --git a/indra/llcorehttp/_httppolicy.h b/indra/llcorehttp/_httppolicy.h
index 3c4126e14b..0b8806a3e2 100644
--- a/indra/llcorehttp/_httppolicy.h
+++ b/indra/llcorehttp/_httppolicy.h
@@ -110,12 +110,6 @@ public:
/// Threading: called by worker thread
void retryOp(const opReqPtr_t &);
- /// Attempt to change the priority of an earlier request.
- /// Request that Shadows HttpService's method
- ///
- /// Threading: called by worker thread
- bool changePriority(HttpHandle handle, HttpRequest::priority_t priority);
-
/// Attempt to cancel a previous request.
/// Shadows HttpService's method as well
///
diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp
index 56f52f1b09..294acd7f63 100644
--- a/indra/llcorehttp/_httpservice.cpp
+++ b/indra/llcorehttp/_httpservice.cpp
@@ -80,6 +80,7 @@ HttpService::HttpService()
HttpService::~HttpService()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
mExitRequested = 1U;
if (RUNNING == sState)
{
@@ -131,6 +132,7 @@ HttpService::~HttpService()
void HttpService::init(HttpRequestQueue * queue)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
llassert_always(! sInstance);
llassert_always(NOT_INITIALIZED == sState);
sInstance = new HttpService();
@@ -145,6 +147,7 @@ void HttpService::init(HttpRequestQueue * queue)
void HttpService::term()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
if (sInstance)
{
if (RUNNING == sState && sInstance->mThread)
@@ -196,6 +199,7 @@ bool HttpService::isStopped()
/// Threading: callable by consumer thread *once*.
void HttpService::startThread()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
llassert_always(! mThread || STOPPED == sState);
llassert_always(INITIALIZED == sState || STOPPED == sState);
@@ -220,22 +224,6 @@ void HttpService::stopRequested()
}
-/// Threading: callable by worker thread.
-bool HttpService::changePriority(HttpHandle handle, HttpRequest::priority_t priority)
-{
- bool found(false);
-
- // Skip the request queue as we currently don't leave earlier
- // requests sitting there. Start with the ready queue...
- found = mPolicy->changePriority(handle, priority);
-
- // If not there, we could try the transport/active queue but priority
- // doesn't really have much effect there so we don't waste cycles.
-
- return found;
-}
-
-
/// Try to find the given request handle on any of the request
/// queues and cancel the operation.
///
@@ -244,6 +232,7 @@ bool HttpService::changePriority(HttpHandle handle, HttpRequest::priority_t prio
/// Threading: callable by worker thread.
bool HttpService::cancel(HttpHandle handle)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
bool canceled(false);
// Request can't be on request queue so skip that.
@@ -264,6 +253,7 @@ bool HttpService::cancel(HttpHandle handle)
/// Threading: callable by worker thread.
void HttpService::shutdown()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
// Disallow future enqueue of requests
mRequestQueue->stopQueue();
@@ -293,6 +283,8 @@ void HttpService::shutdown()
// requested to stop.
void HttpService::threadRun(LLCoreInt::HttpThread * thread)
{
+ LL_PROFILER_SET_THREAD_NAME("HttpService");
+
boost::this_thread::disable_interruption di;
LLThread::registerThreadID();
@@ -300,6 +292,7 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread)
ELoopSpeed loop(REQUEST_SLEEP);
while (! mExitRequested)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
try
{
loop = processRequestQueue(loop);
@@ -344,6 +337,7 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread)
HttpService::ELoopSpeed HttpService::processRequestQueue(ELoopSpeed loop)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpRequestQueue::OpContainer ops;
const bool wait_for_req(REQUEST_SLEEP == loop);
@@ -384,6 +378,7 @@ HttpService::ELoopSpeed HttpService::processRequestQueue(ELoopSpeed loop)
HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
long * ret_value)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
|| opt >= HttpRequest::PO_LAST // ditto
|| (! sOptionDesc[opt].mIsLong) // datatype is long
@@ -416,6 +411,7 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
std::string * ret_value)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
@@ -443,6 +439,7 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
HttpRequest::policyCallback_t * ret_value)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
@@ -472,6 +469,7 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
long value, long * ret_value)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
@@ -517,6 +515,7 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
const std::string & value, std::string * ret_value)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
@@ -548,6 +547,7 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
HttpRequest::policyCallback_t value, HttpRequest::policyCallback_t * ret_value)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h
index d0c37ac195..551a718f20 100644
--- a/indra/llcorehttp/_httpservice.h
+++ b/indra/llcorehttp/_httpservice.h
@@ -146,15 +146,6 @@ public:
/// Threading: callable by worker thread.
void shutdown();
- /// Try to find the given request handle on any of the request
- /// queues and reset the priority (and queue position) of the
- /// request if found.
- ///
- /// @return True if the request was found somewhere.
- ///
- /// Threading: callable by worker thread.
- bool changePriority(HttpHandle handle, HttpRequest::priority_t priority);
-
/// Try to find the given request handle on any of the request
/// queues and cancel the operation.
///
diff --git a/indra/llcorehttp/examples/http_texture_load.cpp b/indra/llcorehttp/examples/http_texture_load.cpp
index c7376042b3..cc53b20add 100644
--- a/indra/llcorehttp/examples/http_texture_load.cpp
+++ b/indra/llcorehttp/examples/http_texture_load.cpp
@@ -469,11 +469,11 @@ bool WorkingSet::reload(LLCore::HttpRequest * hr, LLCore::HttpOptions::ptr_t & o
LLCore::HttpHandle handle;
if (offset || length)
{
- handle = hr->requestGetByteRange(0, 0, buffer, offset, length, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor));
+ handle = hr->requestGetByteRange(0, buffer, offset, length, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor));
}
else
{
- handle = hr->requestGet(0, 0, buffer, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor));
+ handle = hr->requestGet(0, buffer, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor));
}
if (! handle)
{
diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp
index 2687f77217..de3854a101 100644
--- a/indra/llcorehttp/httprequest.cpp
+++ b/indra/llcorehttp/httprequest.cpp
@@ -32,7 +32,6 @@
#include "_httppolicy.h"
#include "_httpoperation.h"
#include "_httpoprequest.h"
-#include "_httpopsetpriority.h"
#include "_httpopcancel.h"
#include "_httpopsetget.h"
@@ -183,16 +182,16 @@ HttpStatus HttpRequest::getStatus() const
HttpHandle HttpRequest::requestGet(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
HttpHandler::ptr_t user_handler)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status;
HttpOpRequest::ptr_t op(new HttpOpRequest());
- if (! (status = op->setupGet(policy_id, priority, url, options, headers)))
+ if (! (status = op->setupGet(policy_id, url, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -210,7 +209,6 @@ HttpHandle HttpRequest::requestGet(policy_t policy_id,
HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,
- priority_t priority,
const std::string & url,
size_t offset,
size_t len,
@@ -218,10 +216,11 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,
const HttpHeaders::ptr_t & headers,
HttpHandler::ptr_t user_handler)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status;
HttpOpRequest::ptr_t op(new HttpOpRequest());
- if (! (status = op->setupGetByteRange(policy_id, priority, url, offset, len, options, headers)))
+ if (! (status = op->setupGetByteRange(policy_id, url, offset, len, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -239,7 +238,6 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,
HttpHandle HttpRequest::requestPost(policy_t policy_id,
- priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -249,7 +247,7 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id,
HttpStatus status;
HttpOpRequest::ptr_t op(new HttpOpRequest());
- if (! (status = op->setupPost(policy_id, priority, url, body, options, headers)))
+ if (! (status = op->setupPost(policy_id, url, body, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -267,7 +265,6 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id,
HttpHandle HttpRequest::requestPut(policy_t policy_id,
- priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -277,7 +274,7 @@ HttpHandle HttpRequest::requestPut(policy_t policy_id,
HttpStatus status;
HttpOpRequest::ptr_t op (new HttpOpRequest());
- if (! (status = op->setupPut(policy_id, priority, url, body, options, headers)))
+ if (! (status = op->setupPut(policy_id, url, body, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -294,7 +291,6 @@ HttpHandle HttpRequest::requestPut(policy_t policy_id,
}
HttpHandle HttpRequest::requestDelete(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -303,7 +299,7 @@ HttpHandle HttpRequest::requestDelete(policy_t policy_id,
HttpStatus status;
HttpOpRequest::ptr_t op(new HttpOpRequest());
- if (!(status = op->setupDelete(policy_id, priority, url, options, headers)))
+ if (!(status = op->setupDelete(policy_id, url, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -320,7 +316,6 @@ HttpHandle HttpRequest::requestDelete(policy_t policy_id,
}
HttpHandle HttpRequest::requestPatch(policy_t policy_id,
- priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -330,7 +325,7 @@ HttpHandle HttpRequest::requestPatch(policy_t policy_id,
HttpStatus status;
HttpOpRequest::ptr_t op (new HttpOpRequest());
- if (!(status = op->setupPatch(policy_id, priority, url, body, options, headers)))
+ if (!(status = op->setupPatch(policy_id, url, body, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -347,7 +342,6 @@ HttpHandle HttpRequest::requestPatch(policy_t policy_id,
}
HttpHandle HttpRequest::requestCopy(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -356,7 +350,7 @@ HttpHandle HttpRequest::requestCopy(policy_t policy_id,
HttpStatus status;
HttpOpRequest::ptr_t op(new HttpOpRequest());
- if (!(status = op->setupCopy(policy_id, priority, url, options, headers)))
+ if (!(status = op->setupCopy(policy_id, url, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -374,7 +368,6 @@ HttpHandle HttpRequest::requestCopy(policy_t policy_id,
}
HttpHandle HttpRequest::requestMove(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -383,7 +376,7 @@ HttpHandle HttpRequest::requestMove(policy_t policy_id,
HttpStatus status;
HttpOpRequest::ptr_t op (new HttpOpRequest());
- if (!(status = op->setupMove(policy_id, priority, url, options, headers)))
+ if (!(status = op->setupMove(policy_id, url, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -483,24 +476,6 @@ HttpHandle HttpRequest::requestCancel(HttpHandle request, HttpHandler::ptr_t use
}
-HttpHandle HttpRequest::requestSetPriority(HttpHandle request, priority_t priority,
- HttpHandler::ptr_t handler)
-{
- HttpStatus status;
-
- HttpOperation::ptr_t op (new HttpOpSetPriority(request, priority));
- op->setReplyPath(mReplyQueue, handler);
- if (! (status = mRequestQueue->addOp(op))) // transfers refcount
- {
- mLastReqStatus = status;
- return LLCORE_HTTP_HANDLE_INVALID;
- }
-
- mLastReqStatus = status;
- return op->getHandle();
-}
-
-
// ====================================
// Utility Methods
// ====================================
diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h
index a418eb6a7a..ca4b9e92bc 100644
--- a/indra/llcorehttp/httprequest.h
+++ b/indra/llcorehttp/httprequest.h
@@ -95,7 +95,6 @@ private:
public:
typedef unsigned int policy_t;
- typedef unsigned int priority_t;
typedef boost::shared_ptr ptr_t;
typedef boost::weak_ptr wptr_t;
@@ -316,8 +315,6 @@ public:
///
/// @param policy_id Default or user-defined policy class under
/// which this request is to be serviced.
- /// @param priority Standard priority scheme inherited from
- /// Indra code base (U32-type scheme).
/// @param url URL with any encoded query parameters to
/// be accessed.
/// @param options Optional instance of an HttpOptions object
@@ -346,7 +343,6 @@ public:
/// case, @see getStatus() will return more info.
///
HttpHandle requestGet(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -377,7 +373,6 @@ public:
/// - Referer:
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param offset Offset of first byte into resource to be returned.
/// @param len Count of bytes to be returned
@@ -387,7 +382,6 @@ public:
/// @return "
///
HttpHandle requestGetByteRange(policy_t policy_id,
- priority_t priority,
const std::string & url,
size_t offset,
size_t len,
@@ -418,7 +412,6 @@ public:
/// - Expect:
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param body Byte stream to be sent as the body. No
/// further encoding or escaping will be done
@@ -429,7 +422,6 @@ public:
/// @return "
///
HttpHandle requestPost(policy_t policy_id,
- priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -459,7 +451,6 @@ public:
/// - Content-Type:
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param body Byte stream to be sent as the body. No
/// further encoding or escaping will be done
@@ -470,7 +461,6 @@ public:
/// @return "
///
HttpHandle requestPut(policy_t policy_id,
- priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -483,7 +473,6 @@ public:
/// encoding and communicating the content types.
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param options @see requestGet()K(optional)
/// @param headers "
@@ -491,7 +480,6 @@ public:
/// @return "
///
HttpHandle requestDelete(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -502,7 +490,6 @@ public:
/// encoding and communicating the content types.
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param body Byte stream to be sent as the body. No
/// further encoding or escaping will be done
@@ -513,7 +500,6 @@ public:
/// @return "
///
HttpHandle requestPatch(policy_t policy_id,
- priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -525,7 +511,6 @@ public:
/// encoding and communicating the content types.
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param options @see requestGet()K(optional)
/// @param headers "
@@ -533,7 +518,6 @@ public:
/// @return "
///
HttpHandle requestCopy(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -544,7 +528,6 @@ public:
/// encoding and communicating the content types.
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param options @see requestGet()K(optional)
/// @param headers "
@@ -552,7 +535,6 @@ public:
/// @return "
///
HttpHandle requestMove(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -593,18 +575,6 @@ public:
HttpHandle requestCancel(HttpHandle request, HttpHandler::ptr_t);
- /// Request that a previously-issued request be reprioritized.
- /// The status of whether the change itself succeeded arrives
- /// via notification.
- ///
- /// @param request Handle of previously-issued request to
- /// be changed.
- /// @param priority New priority value.
- /// @param handler @see requestGet()
- /// @return "
- ///
- HttpHandle requestSetPriority(HttpHandle request, priority_t priority, HttpHandler::ptr_t handler);
-
/// @}
/// @name UtilityMethods
diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp
index 154f6b12e9..3eaac10aeb 100644
--- a/indra/llcorehttp/tests/test_httprequest.hpp
+++ b/indra/llcorehttp/tests/test_httprequest.hpp
@@ -614,7 +614,6 @@ void HttpRequestTestObjectType::test<7>()
// Issue a GET that can't connect
mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_CONNECT);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
"http://127.0.0.1:2/nothing/here",
0,
0,
@@ -716,7 +715,6 @@ void HttpRequestTestObjectType::test<8>()
// Issue a GET that *can* connect
mStatus = HttpStatus(200);
HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
HttpOptions::ptr_t(),
HttpHeaders::ptr_t(),
@@ -812,7 +810,6 @@ void HttpRequestTestObjectType::test<9>()
// Issue a GET that *can* connect
mStatus = HttpStatus(200);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
0,
0,
@@ -913,7 +910,6 @@ void HttpRequestTestObjectType::test<10>()
body->append(body_text, strlen(body_text));
mStatus = HttpStatus(200);
HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
body,
HttpOptions::ptr_t(),
@@ -1020,7 +1016,6 @@ void HttpRequestTestObjectType::test<11>()
body->append(body_text, strlen(body_text));
mStatus = HttpStatus(200);
HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
body,
HttpOptions::ptr_t(),
@@ -1127,7 +1122,6 @@ void HttpRequestTestObjectType::test<12>()
// Issue a GET that *can* connect
mStatus = HttpStatus(200);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
0,
0,
@@ -1240,7 +1234,6 @@ void HttpRequestTestObjectType::test<13>()
regex_container_t::value_type(boost::regex("X-LL-Special", boost::regex::icase),
boost::regex(".*", boost::regex::icase)));
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
0,
0,
@@ -1346,7 +1339,6 @@ void HttpRequestTestObjectType::test<14>()
// Issue a GET that sleeps
mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
0,
0,
@@ -1454,7 +1446,6 @@ void HttpRequestTestObjectType::test<15>()
mStatus = HttpStatus(200);
handler.mCheckContentType = "application/llsd+xml";
HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
HttpOptions::ptr_t(),
HttpHeaders::ptr_t(),
@@ -1609,7 +1600,6 @@ void HttpRequestTestObjectType::test<16>()
boost::regex("X-Reflect-content-encoding", boost::regex::icase),
boost::regex(".*", boost::regex::icase)));
HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
options,
HttpHeaders::ptr_t(),
@@ -1684,7 +1674,6 @@ void HttpRequestTestObjectType::test<16>()
boost::regex("X-Reflect-content-encoding", boost::regex::icase),
boost::regex(".*", boost::regex::icase)));
handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
0,
47,
@@ -1863,7 +1852,6 @@ void HttpRequestTestObjectType::test<17>()
boost::regex("X-Reflect-transfer_encoding", boost::regex::icase),
boost::regex(".*chunked.*", boost::regex::icase)));
HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
ba,
options,
@@ -2049,7 +2037,6 @@ void HttpRequestTestObjectType::test<18>()
boost::regex(".*", boost::regex::icase)));
HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
ba,
options,
@@ -2249,7 +2236,6 @@ void HttpRequestTestObjectType::test<19>()
boost::regex("X-Reflect-content-encoding", boost::regex::icase),
boost::regex(".*", boost::regex::icase)));
HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
options,
headers,
@@ -2457,7 +2443,6 @@ void HttpRequestTestObjectType::test<20>()
boost::regex(".*", boost::regex::icase)));
HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
ba,
options,
@@ -2666,7 +2651,6 @@ void HttpRequestTestObjectType::test<21>()
boost::regex("X-Reflect-content-type", boost::regex::icase),
boost::regex("text/html", boost::regex::icase)));
HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
ba,
options,
@@ -2797,7 +2781,6 @@ void HttpRequestTestObjectType::test<22>()
char buffer[128];
sprintf(buffer, "/bug2295/%d/", i);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + buffer,
0,
25,
@@ -2829,7 +2812,6 @@ void HttpRequestTestObjectType::test<22>()
char buffer[128];
sprintf(buffer, "/bug2295/00000012/%d/", i);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + buffer,
0,
25,
@@ -2861,7 +2843,6 @@ void HttpRequestTestObjectType::test<22>()
char buffer[128];
sprintf(buffer, "/bug2295/inv_cont_range/%d/", i);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + buffer,
0,
25,
@@ -2984,7 +2965,6 @@ void HttpRequestTestObjectType::test<23>()
std::ostringstream url;
url << url_base << i << "/";
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url.str(),
0,
0,
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index 0d8fb4863b..bb603d3d7f 100644
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -418,7 +418,7 @@ bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg
updateApplication(llformat("%s, try %d...", msg.c_str(), i+1));
LL_INFOS("CRASHREPORT") << "POST crash data to " << host << LL_ENDL;
- LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(httpRequest.get(), LLCore::HttpRequest::DEFAULT_POLICY_ID, 0,
+ LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(httpRequest.get(), LLCore::HttpRequest::DEFAULT_POLICY_ID,
host, data, httpOpts, LLCore::HttpHeaders::ptr_t(), LLCore::HttpHandler::ptr_t(new LLCrashLoggerHandler));
if (handle == LLCORE_HTTP_HANDLE_INVALID)
diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp
index 4b7363c8e5..54e49ebcb8 100644
--- a/indra/llfilesystem/lldiskcache.cpp
+++ b/indra/llfilesystem/lldiskcache.cpp
@@ -221,6 +221,7 @@ const std::string LLDiskCache::assetTypeToString(LLAssetType::EType at)
{ LLAssetType::AT_PERSON, "PERSON" },
{ LLAssetType::AT_MESH, "MESH" },
{ LLAssetType::AT_SETTINGS, "SETTINGS" },
+ { LLAssetType::AT_MATERIAL, "MATERIAL" },
{ LLAssetType::AT_UNKNOWN, "UNKNOWN" }
};
diff --git a/indra/llfilesystem/lllfsthread.cpp b/indra/llfilesystem/lllfsthread.cpp
index be8e83a56f..dbb69cd605 100644
--- a/indra/llfilesystem/lllfsthread.cpp
+++ b/indra/llfilesystem/lllfsthread.cpp
@@ -45,8 +45,7 @@ void LLLFSThread::initClass(bool local_is_threaded)
//static
S32 LLLFSThread::updateClass(U32 ms_elapsed)
{
- sLocal->update((F32)ms_elapsed);
- return sLocal->getPending();
+ return sLocal->update((F32)ms_elapsed);
}
//static
@@ -58,6 +57,7 @@ void LLLFSThread::cleanupClass()
{
sLocal->update(0);
}
+ sLocal->shutdown();
delete sLocal;
sLocal = NULL;
}
@@ -65,8 +65,7 @@ void LLLFSThread::cleanupClass()
//----------------------------------------------------------------------------
LLLFSThread::LLLFSThread(bool threaded) :
- LLQueuedThread("LFS", threaded),
- mPriorityCounter(PRIORITY_LOWBITS)
+ LLQueuedThread("LFS", threaded)
{
if(!mLocalAPRFilePoolp)
{
@@ -84,14 +83,12 @@ LLLFSThread::~LLLFSThread()
LLLFSThread::handle_t LLLFSThread::read(const std::string& filename, /* Flawfinder: ignore */
U8* buffer, S32 offset, S32 numbytes,
- Responder* responder, U32 priority)
+ Responder* responder)
{
+ LL_PROFILE_ZONE_SCOPED;
handle_t handle = generateHandle();
- if (priority == 0) priority = PRIORITY_NORMAL | priorityCounter();
- else if (priority < PRIORITY_LOW) priority |= PRIORITY_LOW; // All reads are at least PRIORITY_LOW
-
- Request* req = new Request(this, handle, priority,
+ Request* req = new Request(this, handle,
FILE_READ, filename,
buffer, offset, numbytes,
responder);
@@ -107,13 +104,12 @@ LLLFSThread::handle_t LLLFSThread::read(const std::string& filename, /* Flawfind
LLLFSThread::handle_t LLLFSThread::write(const std::string& filename,
U8* buffer, S32 offset, S32 numbytes,
- Responder* responder, U32 priority)
+ Responder* responder)
{
+ LL_PROFILE_ZONE_SCOPED;
handle_t handle = generateHandle();
- if (priority == 0) priority = PRIORITY_LOW | priorityCounter();
-
- Request* req = new Request(this, handle, priority,
+ Request* req = new Request(this, handle,
FILE_WRITE, filename,
buffer, offset, numbytes,
responder);
@@ -130,11 +126,11 @@ LLLFSThread::handle_t LLLFSThread::write(const std::string& filename,
//============================================================================
LLLFSThread::Request::Request(LLLFSThread* thread,
- handle_t handle, U32 priority,
+ handle_t handle,
operation_t op, const std::string& filename,
U8* buffer, S32 offset, S32 numbytes,
Responder* responder) :
- QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE),
+ QueuedRequest(handle, FLAG_AUTO_COMPLETE),
mThread(thread),
mOperation(op),
mFileName(filename),
@@ -157,6 +153,7 @@ LLLFSThread::Request::~Request()
// virtual, called from own thread
void LLLFSThread::Request::finishRequest(bool completed)
{
+ LL_PROFILE_ZONE_SCOPED;
if (mResponder.notNull())
{
mResponder->completed(completed ? mBytesRead : 0);
@@ -166,6 +163,7 @@ void LLLFSThread::Request::finishRequest(bool completed)
void LLLFSThread::Request::deleteRequest()
{
+ LL_PROFILE_ZONE_SCOPED;
if (getStatus() == STATUS_QUEUED)
{
LL_ERRS() << "Attempt to delete a queued LLLFSThread::Request!" << LL_ENDL;
@@ -180,6 +178,7 @@ void LLLFSThread::Request::deleteRequest()
bool LLLFSThread::Request::processRequest()
{
+ LL_PROFILE_ZONE_SCOPED;
bool complete = false;
if (mOperation == FILE_READ)
{
diff --git a/indra/llfilesystem/lllfsthread.h b/indra/llfilesystem/lllfsthread.h
index 58f658f7ba..f2693a1172 100644
--- a/indra/llfilesystem/lllfsthread.h
+++ b/indra/llfilesystem/lllfsthread.h
@@ -68,7 +68,7 @@ public:
public:
Request(LLLFSThread* thread,
- handle_t handle, U32 priority,
+ handle_t handle,
operation_t op, const std::string& filename,
U8* buffer, S32 offset, S32 numbytes,
Responder* responder);
@@ -120,22 +120,15 @@ public:
// Return a Request handle
handle_t read(const std::string& filename, /* Flawfinder: ignore */
U8* buffer, S32 offset, S32 numbytes,
- Responder* responder, U32 pri=0);
+ Responder* responder);
handle_t write(const std::string& filename,
U8* buffer, S32 offset, S32 numbytes,
- Responder* responder, U32 pri=0);
-
- // Misc
- U32 priorityCounter() { return mPriorityCounter-- & PRIORITY_LOWBITS; } // Use to order IO operations
+ Responder* responder);
// static initializers
static void initClass(bool local_is_threaded = TRUE); // Setup sLocal
static S32 updateClass(U32 ms_elapsed);
static void cleanupClass(); // Delete sLocal
-
-
-private:
- U32 mPriorityCounter;
public:
static LLLFSThread* sLocal; // Default local file thread
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 0fa027c9c3..031471d1fe 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -798,7 +798,6 @@ U8* LLImageBase::allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 si
// LLImageRaw
//---------------------------------------------------------------------------
-S32 LLImageRaw::sGlobalRawMemory = 0;
S32 LLImageRaw::sRawImageCount = 0;
LLImageRaw::LLImageRaw()
@@ -815,6 +814,15 @@ LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components)
++sRawImageCount;
}
+LLImageRaw::LLImageRaw(const U8* data, U16 width, U16 height, S8 components)
+ : LLImageBase()
+{
+ if (allocateDataSize(width, height, components))
+ {
+ memcpy(getData(), data, width * height * components);
+ }
+}
+
LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy)
: LLImageBase()
{
@@ -847,16 +855,13 @@ LLImageRaw::~LLImageRaw()
U8* LLImageRaw::allocateData(S32 size)
{
U8* res = LLImageBase::allocateData(size);
- sGlobalRawMemory += getDataSize();
return res;
}
// virtual
U8* LLImageRaw::reallocateData(S32 size)
{
- sGlobalRawMemory -= getDataSize();
U8* res = LLImageBase::reallocateData(size);
- sGlobalRawMemory += getDataSize();
return res;
}
@@ -869,7 +874,6 @@ void LLImageRaw::releaseData()
// virtual
void LLImageRaw::deleteData()
{
- sGlobalRawMemory -= getDataSize();
LLImageBase::deleteData();
}
@@ -985,6 +989,43 @@ void LLImageRaw::verticalFlip()
}
+bool LLImageRaw::optimizeAwayAlpha()
+{
+ if (getComponents() == 4)
+ {
+ U8* data = getData();
+ U32 pixels = getWidth() * getHeight();
+
+ // check alpha channel for all 255
+ for (U32 i = 0; i < pixels; ++i)
+ {
+ if (data[i * 4 + 3] != 255)
+ {
+ return false;
+ }
+ }
+
+ // alpha channel is all 255, make a new copy of data without alpha channel
+ U8* new_data = (U8*) ll_aligned_malloc_16(getWidth() * getHeight() * 3);
+
+ for (U32 i = 0; i < pixels; ++i)
+ {
+ U32 di = i * 3;
+ U32 si = i * 4;
+ for (U32 j = 0; j < 3; ++j)
+ {
+ new_data[di+j] = data[si+j];
+ }
+ }
+
+ setDataAndSize(new_data, getWidth(), getHeight(), 3);
+
+ return true;
+ }
+
+ return false;
+}
+
void LLImageRaw::expandToPowerOfTwo(S32 max_dim, bool scale_image)
{
// Find new sizes
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 7a588cfb03..8f9e1b3c54 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -184,6 +184,7 @@ protected:
public:
LLImageRaw();
LLImageRaw(U16 width, U16 height, S8 components);
+ LLImageRaw(const U8* data, U16 width, U16 height, S8 components);
LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy = false);
// Construct using createFromFile (used by tools)
//LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false);
@@ -207,6 +208,10 @@ public:
void clear(U8 r=0, U8 g=0, U8 b=0, U8 a=255);
void verticalFlip();
+
+ // if the alpha channel is all 100% opaque, delete it
+ // returns true if alpha channel was deleted
+ bool optimizeAwayAlpha();
static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
@@ -275,7 +280,6 @@ protected:
void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ;
public:
- static S32 sGlobalRawMemory;
static S32 sRawImageCount;
private:
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index e1809dbe59..8dba1641a6 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -146,6 +146,7 @@ bool LLImageJ2C::initEncode(LLImageRaw &raw_image, int blocks_size, int precinct
bool LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
return decodeChannels(raw_imagep, decode_time, 0, 4);
}
@@ -153,6 +154,7 @@ bool LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
// Returns true to mean done, whether successful or not.
bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLTimer elapsed;
bool res = true;
diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
index ff4336d2de..c1ee052997 100644
--- a/indra/llimage/llimageworker.cpp
+++ b/indra/llimage/llimageworker.cpp
@@ -28,64 +28,93 @@
#include "llimageworker.h"
#include "llimagedxt.h"
+#include "threadpool.h"
+
+/*--------------------------------------------------------------------------*/
+class ImageRequest
+{
+public:
+ ImageRequest(const LLPointer& image,
+ S32 discard, BOOL needs_aux,
+ const LLPointer& responder);
+ virtual ~ImageRequest();
+
+ /*virtual*/ bool processRequest();
+ /*virtual*/ void finishRequest(bool completed);
+
+private:
+ // LLPointers stored in ImageRequest MUST be LLPointer instances rather
+ // than references: we need to increment the refcount when storing these.
+ // input
+ LLPointer mFormattedImage;
+ S32 mDiscardLevel;
+ BOOL mNeedsAux;
+ // output
+ LLPointer mDecodedImageRaw;
+ LLPointer mDecodedImageAux;
+ BOOL mDecodedRaw;
+ BOOL mDecodedAux;
+ LLPointer mResponder;
+};
+
//----------------------------------------------------------------------------
// MAIN THREAD
-LLImageDecodeThread::LLImageDecodeThread(bool threaded)
- : LLQueuedThread("imagedecode", threaded)
+LLImageDecodeThread::LLImageDecodeThread(bool /*threaded*/)
{
- mCreationMutex = new LLMutex();
+ mThreadPool.reset(new LL::ThreadPool("ImageDecode", 8));
+ mThreadPool->start();
}
//virtual
LLImageDecodeThread::~LLImageDecodeThread()
-{
- delete mCreationMutex ;
-}
+{}
// MAIN THREAD
// virtual
size_t LLImageDecodeThread::update(F32 max_time_ms)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- LLMutexLock lock(mCreationMutex);
- for (creation_list_t::iterator iter = mCreationList.begin();
- iter != mCreationList.end(); ++iter)
- {
- creation_info& info = *iter;
- ImageRequest* req = new ImageRequest(info.handle, info.image,
- info.priority, info.discard, info.needs_aux,
- info.responder);
-
- bool res = addRequest(req);
- if (!res)
- {
- LL_ERRS() << "request added after LLLFSThread::cleanupClass()" << LL_ENDL;
- }
- }
- mCreationList.clear();
- S32 res = LLQueuedThread::update(max_time_ms);
- return res;
+ return getPending();
}
-LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image,
- U32 priority, S32 discard, BOOL needs_aux, Responder* responder)
+size_t LLImageDecodeThread::getPending()
+{
+ return mThreadPool->getQueue().size();
+}
+
+LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(
+ const LLPointer& image,
+ S32 discard,
+ BOOL needs_aux,
+ const LLPointer& responder)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- LLMutexLock lock(mCreationMutex);
- handle_t handle = generateHandle();
- mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder));
- return handle;
+
+ // Instantiate the ImageRequest right in the lambda, why not?
+ bool posted = mThreadPool->getQueue().post(
+ [req = ImageRequest(image, discard, needs_aux, responder)]
+ () mutable
+ {
+ auto done = req.processRequest();
+ req.finishRequest(done);
+ });
+ if (! posted)
+ {
+ LL_DEBUGS() << "Tried to start decoding on shutdown" << LL_ENDL;
+ // should this return 0?
+ }
+
+ // It's important to our consumer (LLTextureFetchWorker) that we return a
+ // nonzero handle. It is NOT important that the nonzero handle be unique:
+ // nothing is ever done with it except to compare it to zero, or zero it.
+ return 17;
}
-// Used by unit test only
-// Returns the size of the mutex guarded list as an indication of sanity
-S32 LLImageDecodeThread::tut_size()
+void LLImageDecodeThread::shutdown()
{
- LLMutexLock lock(mCreationMutex);
- S32 res = mCreationList.size();
- return res;
+ mThreadPool->close();
}
LLImageDecodeThread::Responder::~Responder()
@@ -94,11 +123,10 @@ LLImageDecodeThread::Responder::~Responder()
//----------------------------------------------------------------------------
-LLImageDecodeThread::ImageRequest::ImageRequest(handle_t handle, LLImageFormatted* image,
- U32 priority, S32 discard, BOOL needs_aux,
- LLImageDecodeThread::Responder* responder)
- : LLQueuedThread::QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE),
- mFormattedImage(image),
+ImageRequest::ImageRequest(const LLPointer& image,
+ S32 discard, BOOL needs_aux,
+ const LLPointer& responder)
+ : mFormattedImage(image),
mDiscardLevel(discard),
mNeedsAux(needs_aux),
mDecodedRaw(FALSE),
@@ -107,7 +135,7 @@ LLImageDecodeThread::ImageRequest::ImageRequest(handle_t handle, LLImageFormatte
{
}
-LLImageDecodeThread::ImageRequest::~ImageRequest()
+ImageRequest::~ImageRequest()
{
mDecodedImageRaw = NULL;
mDecodedImageAux = NULL;
@@ -118,10 +146,10 @@ LLImageDecodeThread::ImageRequest::~ImageRequest()
// Returns true when done, whether or not decode was successful.
-bool LLImageDecodeThread::ImageRequest::processRequest()
+bool ImageRequest::processRequest()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- const F32 decode_time_slice = .1f;
+ const F32 decode_time_slice = 0.f; //disable time slicing
bool done = true;
if (!mDecodedRaw && mFormattedImage.notNull())
{
@@ -145,7 +173,7 @@ bool LLImageDecodeThread::ImageRequest::processRequest()
mFormattedImage->getHeight(),
mFormattedImage->getComponents());
}
- done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice); // 1ms
+ done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice);
// some decoders are removing data when task is complete and there were errors
mDecodedRaw = done && mDecodedImageRaw->getData();
}
@@ -158,14 +186,14 @@ bool LLImageDecodeThread::ImageRequest::processRequest()
mFormattedImage->getHeight(),
1);
}
- done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4); // 1ms
+ done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4);
mDecodedAux = done && mDecodedImageAux->getData();
}
return done;
}
-void LLImageDecodeThread::ImageRequest::finishRequest(bool completed)
+void ImageRequest::finishRequest(bool completed)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (mResponder.notNull())
@@ -175,10 +203,3 @@ void LLImageDecodeThread::ImageRequest::finishRequest(bool completed)
}
// Will automatically be deleted
}
-
-// Used by unit test only
-// Checks that a responder exists for this instance so that something can happen when completion is reached
-bool LLImageDecodeThread::ImageRequest::tut_isOK()
-{
- return mResponder.notNull();
-}
diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h
index 54814c24c5..ca4c0d93d0 100644
--- a/indra/llimage/llimageworker.h
+++ b/indra/llimage/llimageworker.h
@@ -29,9 +29,9 @@
#include "llimage.h"
#include "llpointer.h"
-#include "llworkerthread.h"
+#include "threadpool_fwd.h"
-class LLImageDecodeThread : public LLQueuedThread
+class LLImageDecodeThread
{
public:
class Responder : public LLThreadSafeRefCount
@@ -42,63 +42,24 @@ public:
virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) = 0;
};
- class ImageRequest : public LLQueuedThread::QueuedRequest
- {
- protected:
- virtual ~ImageRequest(); // use deleteRequest()
-
- public:
- ImageRequest(handle_t handle, LLImageFormatted* image,
- U32 priority, S32 discard, BOOL needs_aux,
- LLImageDecodeThread::Responder* responder);
-
- /*virtual*/ bool processRequest();
- /*virtual*/ void finishRequest(bool completed);
-
- // Used by unit tests to check the consitency of the request instance
- bool tut_isOK();
-
- private:
- // input
- LLPointer mFormattedImage;
- S32 mDiscardLevel;
- BOOL mNeedsAux;
- // output
- LLPointer mDecodedImageRaw;
- LLPointer mDecodedImageAux;
- BOOL mDecodedRaw;
- BOOL mDecodedAux;
- LLPointer mResponder;
- };
-
public:
LLImageDecodeThread(bool threaded = true);
virtual ~LLImageDecodeThread();
- handle_t decodeImage(LLImageFormatted* image,
- U32 priority, S32 discard, BOOL needs_aux,
- Responder* responder);
+ // meant to resemble LLQueuedThread::handle_t
+ typedef U32 handle_t;
+ handle_t decodeImage(const LLPointer& image,
+ S32 discard, BOOL needs_aux,
+ const LLPointer& responder);
+ size_t getPending();
size_t update(F32 max_time_ms);
+ void shutdown();
- // Used by unit tests to check the consistency of the thread instance
- S32 tut_size();
-
private:
- struct creation_info
- {
- handle_t handle;
- LLPointer image;
- U32 priority;
- S32 discard;
- BOOL needs_aux;
- LLPointer