65bf003397e55927776facd7654de161ea8c1e20
lrnassar
Fri Jan 30 15:59:33 2026 -0800
Downloading our major CDNs and changing their references to all be local, there are some more corner cases that were low priority as discussed in the ticket. This work is done to improve performance, expecially for overseas users. Refs #33998
diff --git src/hg/hgCollection/hgCollection.c src/hg/hgCollection/hgCollection.c
index 649bf70d1cc..bad148aac2d 100644
--- src/hg/hgCollection/hgCollection.c
+++ src/hg/hgCollection/hgCollection.c
@@ -1,1081 +1,1081 @@
/* hgCollection - hub builder */
/* Copyright (C) 2017 The Regents of the University of California
* See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */
#include "common.h"
#include "cartTrackDb.h"
#include "trackHub.h"
#include "trashDir.h"
#include "hubConnect.h"
#include "hui.h"
#include "grp.h"
#include "cheapcgi.h"
#include "jsHelper.h"
#include "web.h"
#include "knetUdc.h"
#include "api.h"
#include "genbank.h"
#include "htmshell.h"
#include "jsonParse.h"
#include "customComposite.h"
#include "stdlib.h"
#include "wikiLink.h"
/* Tool tips */
#define COLLECTION_TITLE "Double-click to edit name and color"
#define FOLDER_TITLE "Click to open node"
#define TRACK_TITLE "Press Green Plus to add track to collection"
/* Global Variables */
struct hash *oldVars = NULL; /* The cart before new cgi stuff added. */
// Null terminated list of CGI Variables we don't want to save permanently:
char *excludeVars[] = {"Submit", "submit", "cmd", "track", "collection", "jsonp", NULL,};
struct track
{
struct track *next;
struct track *trackList;
struct trackDb *tdb;
char *name;
char *shortLabel;
char *longLabel;
unsigned long color;
};
struct trackDbRef
{
struct trackDbRef *next;
struct trackDb *tdb;
struct grp *grp;
double priority;
int order;
};
static char *makeUniqueLabel(struct hash *labelHash, char *label)
// Make the short label of this track unique.
{
if (hashLookup(labelHash, label) == NULL)
{
hashStore(labelHash, label);
return label;
}
unsigned count = 1;
char buffer[4096];
for(;; count++)
{
safef(buffer, sizeof buffer, "%s (%d)", label, count);
if (hashLookup(labelHash, buffer) == NULL)
{
hashStore(labelHash, buffer);
return cloneString(buffer);
}
}
return NULL;
}
static char *makeUniqueName(struct hash *nameHash, char *name)
// Make the name of this track unique.
{
char *skipHub = trackHubSkipHubName(name);
if (hashLookup(nameHash, skipHub) == NULL)
{
hashStore(nameHash, skipHub);
return skipHub;
}
char base[4096];
safef(base, sizeof base, "%s_%lx",skipHub, time(NULL) - 1520629086);
unsigned count = 0;
char buffer[4096];
for(;; count++)
{
safef(buffer, sizeof buffer, "%s%d", base, count);
if (hashLookup(nameHash, buffer) == NULL)
{
hashStore(nameHash, buffer);
return cloneString(buffer);
}
}
return NULL;
}
static struct trackDb *createComposite(char *collectionName, char *shortLabel, char *longLabel, long color, int priority)
// Create a trackDb entry for a new composite
{
struct trackDb *tdb;
char buffer[512];
AllocVar(tdb);
tdb->settingsHash = newHash(5);
tdb->type = cloneString("mathWig");
safef(buffer, sizeof buffer, "%ld,%ld,%ld", 0xff & (color >> 16),0xff & (color >> 8),0xff & color);
hashAdd(tdb->settingsHash, "color", cloneString(buffer));
safef(buffer, sizeof buffer, "%d", priority);
hashAdd(tdb->settingsHash, "priority", cloneString(buffer));
hashAdd(tdb->settingsHash, "track", collectionName);
hashAdd(tdb->settingsHash, "shortLabel", shortLabel);
hashAdd(tdb->settingsHash, "longLabel", longLabel);
hashAdd(tdb->settingsHash, "autoScale", "on");
hashAdd(tdb->settingsHash, "compositeTrack", "on");
hashAdd(tdb->settingsHash, "aggregate", "none");
hashAdd(tdb->settingsHash, "type", "mathWig");
hashAdd(tdb->settingsHash, "visibility", "full");
hashAdd(tdb->settingsHash, "customized", "on");
hashAdd(tdb->settingsHash, "maxHeightPixels", "10000:30:11");
hashAdd(tdb->settingsHash, "showSubtrackColorOnUi", "on");
hashAdd(tdb->settingsHash, CUSTOM_COMPOSITE_SETTING, "on");
return tdb;
}
static boolean trackCanBeAdded(struct trackDb *tdb)
// are we allowing this track into a custom composite
{
return (tdb->subtracks == NULL) && !startsWith("wigMaf",tdb->type) && (startsWith("wig",tdb->type) || startsWith("bigWig",tdb->type) || startsWith("bedGraph",tdb->type)) ;
}
static char *escapeLabel(char *label)
// put a blackslash in front of any single quotes in the input
{
char buffer[4096], *eptr = buffer;
for(; *label; label++)
{
if (*label == '\'')
{
*eptr++ = '\\';
*eptr++ = '\'';
}
else
*eptr++ = *label;
}
*eptr = 0;
return cloneString(buffer);
}
static void trackToClient(char *parent, struct trackDb *tdb, boolean user)
// output list elements for a group
{
char *userString = "";
char *title;
if (user)
title = COLLECTION_TITLE;
else if (tdb->subtracks)
title = FOLDER_TITLE;
else
title = TRACK_TITLE;
if (tdb->subtracks)
userString = "icon:'../images/folderC.png',children:true,";
else if (user)
userString = "icon:'fa fa-minus-square',";
else
userString = "icon:'fa fa-plus',";
#define IMAKECOLOR_32(r,g,b) ( ((unsigned int)b<<0) | ((unsigned int)g << 8) | ((unsigned int)r << 16))
jsInlineF("{%s id:'%s',li_attr:{title:'%s',shortlabel:'%s', longlabel:'%s',color:'#%06x',name:'%s'},text:'%s (%s)',parent:'%s'}",userString, trackHubSkipHubName(tdb->track),title, escapeLabel(tdb->shortLabel), escapeLabel(tdb->longLabel), IMAKECOLOR_32(tdb->colorR,tdb->colorG,tdb->colorB),trackHubSkipHubName(tdb->track),escapeLabel(tdb->shortLabel),escapeLabel(tdb->longLabel),parent);
}
static void outHubHeader(FILE *f, char *db)
// output a track hub header
{
fprintf(f,"hub hub1\n\
shortLabel Track Collections\n\
longLabel Track Collections\n\
useOneFile on\n\
email genome-www@soe.ucsc.edu\n\n");
fprintf(f,"genome %s\n\n", db);
}
static char *getHubName(struct cart *cart, char *db, boolean doCreate)
// get the name of the hub to use for user collections. Create the hub if doCreate is TRUE
{
struct tempName hubTn;
char buffer[4096];
safef(buffer, sizeof buffer, "%s-%s", customCompositeCartName, db);
char *hubName = cartOptionalString(cart, buffer);
int fd = -1;
if (!doCreate && (hubName == NULL))
return NULL;
if ((hubName == NULL) || ((fd = open(hubName, 0)) < 0))
{
trashDirDateFile(&hubTn, "hgComposite", "hub", ".txt");
hubName = cloneString(hubTn.forCgi);
cartSetString(cart, buffer, hubName);
FILE *f = mustOpen(hubName, "a");
outHubHeader(f, db);
fclose(f);
}
if (fd >= 0)
close(fd);
cartSetString(cart, "hubUrl", hubName);
cartSetString(cart, hgHubConnectRemakeTrackHub, hubName);
return hubName;
}
static bool subtrackEnabledInTdb(struct trackDb *subTdb)
/* Return TRUE unless the subtrack was declared with "subTrack ... off". */
{
bool enabled = TRUE;
char *words[2];
char *setting;
if ((setting = trackDbLocalSetting(subTdb, "parent")) != NULL)
{
if (chopLine(cloneString(setting), words) >= 2)
if (sameString(words[1], "off"))
enabled = FALSE;
}
else
return subTdb->visibility != tvHide;
return enabled;
}
static bool isSubtrackVisible(struct cart *cart, struct trackDb *tdb)
/* Has this subtrack not been deselected in hgTrackUi or declared with
* * "subTrack ... off"? -- assumes composite track is visible. */
{
boolean overrideComposite = (NULL != cartOptionalString(cart, tdb->track));
bool enabledInTdb = subtrackEnabledInTdb(tdb);
char option[1024];
safef(option, sizeof(option), "%s_sel", tdb->track);
boolean enabled = cartUsualBoolean(cart, option, enabledInTdb);
if (overrideComposite)
enabled = TRUE;
return enabled;
}
static bool isParentVisible(struct cart *cart, struct trackDb *tdb)
// Are this track's parents visible?
{
if (tdb->parent == NULL)
return TRUE;
if (!isParentVisible(cart, tdb->parent))
return FALSE;
char *cartVis = cartOptionalString(cart, tdb->parent->track);
boolean vis;
if (cartVis != NULL)
vis = differentString(cartVis, "hide");
else if (tdbIsSuperTrack(tdb->parent))
vis = tdb->parent->isShow;
else
vis = tdb->parent->visibility != tvHide;
return vis;
}
static void checkForVisible(struct cart *cart, struct grp *grp, struct trackDbRef **list, struct trackDb *tdb, double priority, double multiplier)
/* Walk the trackDb hierarchy looking for visible leaf tracks. */
{
struct trackDb *subTdb;
char buffer[4096];
if (tdb->subtracks)
{
for(subTdb = tdb->subtracks; subTdb; subTdb = subTdb->next)
checkForVisible(cart, grp, list, subTdb, priority + tdb->priority * multiplier, multiplier / 100.0);
}
else
{
boolean isVisible = FALSE;
if (tdb->parent == NULL)
{
char *cartVis = cartOptionalString(cart, tdb->track);
if (cartVis == NULL)
isVisible = tdb->visibility != tvHide;
else
isVisible = differentString(cartVis, "hide");
}
else if (isParentVisible(cart, tdb) && isSubtrackVisible(cart, tdb))
isVisible = TRUE;
if (isVisible)
{
struct trackDbRef *tdbRef;
AllocVar(tdbRef);
tdbRef->tdb = tdb;
tdbRef->grp = grp;
slAddHead(list, tdbRef);
safef(buffer, sizeof buffer, "%s_imgOrd", tdb->track);
tdbRef->order = cartUsualInt(cart, buffer, 0);
tdbRef->priority = priority + multiplier * tdb->priority;
}
}
}
static int tdbRefCompare (const void *va, const void *vb)
// Compare to sort on imgTrack->order.
{
const struct trackDbRef *a = *((struct trackDbRef **)va);
const struct trackDbRef *b = *((struct trackDbRef **)vb);
int dif = a->order - b->order;
if (dif == 0)
{
double ddif = a->priority - b->priority ;
if (ddif < 0)
dif = -1;
else if (ddif > 0)
dif = 1;
}
if (dif == 0)
dif = strcasecmp(a->tdb->shortLabel, b->tdb->shortLabel);
return dif;
}
static void addVisibleTracks(struct hash *groupHash, struct dyString *rootChildren, struct cart *cart, struct trackDb *trackList)
// add the visible tracks table rows.
{
struct trackDb *tdb;
struct trackDbRef *tdbRefList = NULL, *tdbRef;
for(tdb = trackList; tdb; tdb = tdb->next)
{
double priority = tdb->priority/100.0;
struct grp *grp = hashFindVal(groupHash, tdb->grp);
if (grp)
priority += grp->priority;
checkForVisible(cart, grp, &tdbRefList, tdb, priority, 1.0/100.0);
}
slSort(&tdbRefList, tdbRefCompare);
if (!isEmpty(rootChildren->string))
dyStringPrintf(rootChildren, ",");
dyStringPrintf(rootChildren, "{icon:'../images/folderC.png',id:'visible', text:'Visible Tracks', parent:'#', li_attr:{title:'%s'} ", FOLDER_TITLE);
if (tdbRefList != NULL)
dyStringPrintf(rootChildren, ",children:true");
dyStringPrintf(rootChildren, "}");
jsInlineF("trackData['visible'] = [");
for(tdbRef = tdbRefList; tdbRef; tdbRef = tdbRef->next)
{
trackToClient("visible", tdbRef->tdb, FALSE);
if (tdbRef->next != NULL)
jsInlineF(",");
}
jsInlineF("];");
}
void subTracksToClient(char *arrayName, struct trackDb *parentTdb, boolean user)
{
if (parentTdb->subtracks == NULL)
return;
jsInlineF("%s['%s'] = [", arrayName, trackHubSkipHubName(parentTdb->track));
boolean first = TRUE;
struct trackDb *tdb;
for(tdb = parentTdb->subtracks; tdb; tdb = tdb->next)
{
if (!first)
jsInlineF(",");
trackToClient(trackHubSkipHubName(parentTdb->track), tdb, user);
first = FALSE;
}
jsInlineF("];");
for(tdb = parentTdb->subtracks; tdb; tdb = tdb->next)
subTracksToClient(arrayName,tdb, user);
}
void addSubtrackNames(struct dyString *dy, struct trackDb *parentTdb)
{
if (parentTdb->subtracks == NULL)
return;
struct trackDb *tdb;
for(tdb = parentTdb->subtracks; tdb; tdb = tdb->next)
{
dyStringPrintf(dy, "collectionNames['%s']=1;", trackHubSkipHubName(tdb->track));
addSubtrackNames(dy, tdb);
}
}
static void doTable(struct cart *cart, char *db, struct grp *groupList, struct trackDb *trackList)
// output the tree table
{
char *hubName = hubNameFromUrl(getHubName(cart, db, FALSE));
struct grp *curGroup;
struct hash *groupHash = newHash(10);
int count = 0;
for(curGroup = groupList; curGroup; curGroup = curGroup->next)
{
if (curGroup->priority == 0)
curGroup->priority = count--;
hashAdd(groupHash, curGroup->name, curGroup);
}
curGroup = NULL;
if (hubName != NULL)
curGroup = hashFindVal(groupHash, hubName);
jsInlineF("var collectionData = []; ");
struct dyString *dyNames = dyStringNew(1024);
struct dyString *dyLabels = dyStringNew(1024);
jsInlineF("var collectionNames = [];");
jsInlineF("var collectionLabels = [];");
if (curGroup != NULL)
{
// print out all the tracks in all the collections
struct trackDb *tdb;
jsInlineF("collectionData['#'] = [");
boolean first = TRUE;
for(tdb = trackList; tdb; tdb = tdb->next)
{
if (sameString(tdb->grp, hubName))
{
if (!first)
{
jsInlineF(",");
}
trackToClient("#", tdb, TRUE);
dyStringPrintf(dyNames, "collectionNames['%s']=1;", trackHubSkipHubName(tdb->track));
dyStringPrintf(dyLabels, "collectionLabels['%s']=1;", tdb->shortLabel);
first = FALSE;
}
}
jsInlineF("];");
for(tdb = trackList; tdb; tdb = tdb->next)
{
if ( sameString(tdb->grp, curGroup->name))
{
subTracksToClient("collectionData", tdb, TRUE);
addSubtrackNames(dyNames, tdb);
}
}
}
else
jsInlineF("collectionData['#'] = [];");
jsInlineF("%s", dyNames->string);
jsInlineF("%s", dyLabels->string);
jsInlineF("var trackData = []; ");
struct dyString *rootChildren = dyStringNew(512);
addVisibleTracks(groupHash, rootChildren, cart, trackList);
for(curGroup = groupList; curGroup; curGroup = curGroup->next)
{
if ((hubName != NULL) && sameString(curGroup->name, hubName))
continue;
if (!isEmpty(rootChildren->string))
dyStringPrintf(rootChildren, ",");
dyStringPrintf(rootChildren, "{icon:'../images/folderC.png',id:'%s', text:'%s', parent:'#', children:true,li_attr:{title:'%s'}}", curGroup->name, escapeLabel(curGroup->label), FOLDER_TITLE);
struct trackDb *tdb;
jsInlineF("trackData['%s'] = [", curGroup->name);
boolean first = TRUE;
for(tdb = trackList; tdb; tdb = tdb->next)
{
if ( sameString(tdb->grp, curGroup->name))
{
if (!first)
jsInlineF(",");
trackToClient(curGroup->name, tdb, FALSE);
first = FALSE;
}
}
jsInlineF("];");
for(tdb = trackList; tdb; tdb = tdb->next)
{
if ( sameString(tdb->grp, curGroup->name))
subTracksToClient("trackData", tdb, FALSE);
}
}
jsInlineF("trackData['#'] = [%s];", rootChildren->string);
jsInlineF("var collectionTitle='%s';\n", COLLECTION_TITLE);
jsInlineF("var folderTitle='%s';\n", FOLDER_TITLE);
jsInlineF("var trackTitle='%s';\n", TRACK_TITLE);
jsInlineF("hgCollection.init();\n");
}
static void printHelp()
// print out the help page
{
puts(
"
\n"
"