public String getLogs()

in sdk/appcenter/src/main/java/com/microsoft/appcenter/persistence/DatabasePersistence.java [421:568]


    public String getLogs(@NonNull String group, @NonNull Collection<String> pausedTargetKeys, @IntRange(from = 0) int limit, @NonNull List<Log> outLogs) {

        /* Log. */
        AppCenterLog.debug(LOG_TAG, "Trying to get " + limit + " logs from the Persistence database for " + group);

        /* Query database. */
        SQLiteQueryBuilder builder = SQLiteUtils.newSQLiteQueryBuilder();
        builder.appendWhere(COLUMN_GROUP + " = ?");
        List<String> selectionArgs = new ArrayList<>();
        selectionArgs.add(group);
        if (!pausedTargetKeys.isEmpty()) {
            StringBuilder filter = new StringBuilder();
            for (int i = 0; i < pausedTargetKeys.size(); i++) {
                filter.append("?,");
            }
            filter.deleteCharAt(filter.length() - 1);
            builder.appendWhere(" AND ");
            builder.appendWhere(COLUMN_TARGET_KEY + " NOT IN (" + filter.toString() + ")");
            selectionArgs.addAll(pausedTargetKeys);
        }

        /* Add logs to output parameter after deserialization if logs are not already sent. */
        int count = 0;
        Map<Long, Log> candidates = new LinkedHashMap<>();
        List<Long> failedDbIdentifiers = new ArrayList<>();
        File largePayloadGroupDirectory = getLargePayloadGroupDirectory(group);
        String[] selectionArgsArray = selectionArgs.toArray(new String[0]);
        Cursor cursor = null;
        ContentValues values;
        try {
            cursor = mDatabaseManager.getCursor(builder, null, selectionArgsArray, GET_SORT_ORDER);
        } catch (RuntimeException e) {
            AppCenterLog.error(LOG_TAG, "Failed to get logs: ", e);
        }
        while (cursor != null &&
                (values = mDatabaseManager.nextValues(cursor)) != null &&
                count < limit) {
            Long dbIdentifier = values.getAsLong(PRIMARY_KEY);

            /*
             * When we can't even read the identifier (in this case ContentValues is most likely empty).
             * That probably means it contained a record larger than 2MB (from a previous SDK version)
             * and we hit the cursor limit.
             * Get rid of first non pending log.
             */
            if (dbIdentifier == null) {
                AppCenterLog.error(LOG_TAG, "Empty database record, probably content was larger than 2MB, need to delete as it's now corrupted.");
                List<Long> corruptedIds = getLogsIds(builder, selectionArgsArray);
                for (Long corruptedId : corruptedIds) {
                    if (!mPendingDbIdentifiers.contains(corruptedId) && !candidates.containsKey(corruptedId)) {

                        /* Found the record to delete that we could not read when selecting all fields. */
                        deleteLog(largePayloadGroupDirectory, corruptedId);
                        AppCenterLog.error(LOG_TAG, "Empty database corrupted empty record deleted, id=" + corruptedId);
                        break;
                    }
                }
                continue;
            }

            /* If the log is already in pending state, then skip. Otherwise put the log to candidate container. */
            if (!mPendingDbIdentifiers.contains(dbIdentifier)) {
                try {

                    /* Deserialize JSON to Log. */
                    String logPayload;
                    String databasePayload = values.getAsString(COLUMN_LOG);
                    if (databasePayload == null) {
                        File file = getLargePayloadFile(largePayloadGroupDirectory, dbIdentifier);
                        AppCenterLog.debug(LOG_TAG, "Read payload file " + file);
                        logPayload = FileManager.read(file);
                        if (logPayload == null) {
                            throw new JSONException("Log payload is null and not stored as a file.");
                        }
                    } else {
                        logPayload = databasePayload;
                    }
                    String databasePayloadType = values.getAsString(COLUMN_DATA_TYPE);
                    Log log = getLogSerializer().deserializeLog(logPayload, databasePayloadType);

                    /* Restore target token. */
                    String targetToken = values.getAsString(COLUMN_TARGET_TOKEN);
                    if (targetToken != null) {
                        CryptoUtils.DecryptedData data = CryptoUtils.getInstance(mContext).decrypt(targetToken);
                        log.addTransmissionTarget(data.getDecryptedData());
                    }

                    /* Add log to list and count. */
                    candidates.put(dbIdentifier, log);
                    count++;
                } catch (JSONException e) {

                    /* If it is not able to deserialize, delete and get another log. */
                    AppCenterLog.error(LOG_TAG, "Cannot deserialize a log in the database", e);

                    /* Put the failed identifier to delete. */
                    failedDbIdentifiers.add(dbIdentifier);
                }
            }
        }
        if (cursor != null) {
            try {
                cursor.close();
            } catch (RuntimeException ignore) {
            }
        }

        /* Delete any logs that cannot be de-serialized. */
        if (failedDbIdentifiers.size() > 0) {
            for (long id : failedDbIdentifiers) {
                deleteLog(largePayloadGroupDirectory, id);
            }
            AppCenterLog.warn(LOG_TAG, "Deleted logs that cannot be deserialized");
        }

        /* No logs found. */
        if (candidates.size() <= 0) {
            AppCenterLog.debug(LOG_TAG, "No logs found in the Persistence database at the moment");
            return null;
        }

        /* Generate an ID. */
        String id = UUID.randomUUID().toString();

        /* Log. */
        AppCenterLog.debug(LOG_TAG, "Returning " + candidates.size() + " log(s) with an ID, " + id);
        AppCenterLog.debug(LOG_TAG, "The SID/ID pairs for returning log(s) is/are:");
        List<Long> pendingDbIdentifiersGroup = new ArrayList<>();
        for (Map.Entry<Long, Log> entry : candidates.entrySet()) {
            Long dbIdentifier = entry.getKey();

            /* Change a database identifier to pending state. */
            mPendingDbIdentifiers.add(dbIdentifier);

            /* Store a database identifier to a group of the ID. */
            pendingDbIdentifiersGroup.add(dbIdentifier);

            /* Add to output parameter. */
            outLogs.add(entry.getValue());

            /* Log. */
            AppCenterLog.debug(LOG_TAG, "\t" + entry.getValue().getSid() + " / " + dbIdentifier);
        }

        /* Update pending IDs. */
        mPendingDbIdentifiersGroups.put(group + id, pendingDbIdentifiersGroup);
        return id;
    }